From 296e9a228805eb9a0692c5a1e4304c4e485dc385 Mon Sep 17 00:00:00 2001 From: Soren Hein Date: Thu, 4 Dec 2014 08:46:58 +0100 Subject: [PATCH 001/199] Bug fix affecting solve with given moves Actually two bugs, the first one with no known effect: mv.sequence should of course be 0 to begin with. The move object was not being initialized prior to insertion of a given move. --- src/SolverIF.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/SolverIF.cpp b/src/SolverIF.cpp index d7404df6..8457c8d0 100644 --- a/src/SolverIF.cpp +++ b/src/SolverIF.cpp @@ -238,7 +238,29 @@ int STDCALL SolveBoard( { mv.rank = dl.currentTrickRank[k]; mv.suit = dl.currentTrickSuit[k]; - mv.sequence = dl.currentTrickSuit[k]; + mv.sequence = 0; + + thrp->moves.Init( + trick, + k, + dl.currentTrickRank, + dl.currentTrickSuit, + thrp->lookAheadPos.rankInSuit, + thrp->trump, + thrp->lookAheadPos.first[iniDepth]); + + if (k == 0) + thrp->moves.MoveGen0( + trick, + &thrp->lookAheadPos, + &thrp->bestMove[iniDepth], + &thrp->bestMoveTT[iniDepth], + thrp->rel); + else + thrp->moves.MoveGen123( + trick, + k, + &thrp->lookAheadPos); thrp->lookAheadPos.move[iniDepth + handRelFirst - k] = mv; thrp->moves.MakeSpecific(&mv, trick, k); From 9c23db378a8f0a18aa0dec9a184f645ea839487e Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Fri, 5 Dec 2014 13:57:21 +0100 Subject: [PATCH 002/199] Added Makefile for shared object on Linux --- src/Makefiles/Makefile_linux_shared | 151 ++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 src/Makefiles/Makefile_linux_shared diff --git a/src/Makefiles/Makefile_linux_shared b/src/Makefiles/Makefile_linux_shared new file mode 100644 index 00000000..485c9a09 --- /dev/null +++ b/src/Makefiles/Makefile_linux_shared @@ -0,0 +1,151 @@ +# 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 = -fPIC -g -O3 -flto -fopenmp -mtune=generic -Wno-write-strings + +LD_FLAGS = \ + -Wl,-O1 \ + -Wl,--sort-common \ + -Wl,--as-needed \ + -Wl,-z \ + -Wl,relro + + +# 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) $(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 + + +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 + +%.o: %.cpp + $(CC) $(CC_FULL_FLAGS) $(DDS_THR) -c $< + +depend: + makedepend -Y -- $(CC_FLAGS) -- $(SOURCE_FILES) + +clean: + rm -f $(O_FILES) $(SHARED_LIB) + +install: + cp $(SHARED_LIB) /usr/lib + + +# DO NOT DELETE + +dds.o: ../include/dll.h dds.h debug.h portab.h TransTable.h Timer.h ABstats.h +dds.o: Moves.h Stats.h Scheduler.h Init.h +ABsearch.o: dds.h debug.h 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 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 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 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 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 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 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 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 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 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 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 portab.h TransTable.h ../include/dll.h +Scheduler.o: Timer.h ABstats.h Moves.h Stats.h +SolveBoard.o: dds.h debug.h 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 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 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 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 portab.h TransTable.h ../include/dll.h Timer.h +TransTable.o: ABstats.h Moves.h Stats.h Scheduler.h From bb436e449d41ec51b435643deb78cea9c710463b Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Fri, 5 Dec 2014 18:47:23 +0100 Subject: [PATCH 003/199] Portab.h now in include folder. Reflecting those changes --- src/Makefiles/Makefile_linux_shared | 84 +++++++++++++++-------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/src/Makefiles/Makefile_linux_shared b/src/Makefiles/Makefile_linux_shared index 485c9a09..85da9492 100644 --- a/src/Makefiles/Makefile_linux_shared +++ b/src/Makefiles/Makefile_linux_shared @@ -107,45 +107,47 @@ install: # DO NOT DELETE -dds.o: ../include/dll.h dds.h debug.h portab.h TransTable.h Timer.h ABstats.h -dds.o: Moves.h Stats.h Scheduler.h Init.h -ABsearch.o: dds.h debug.h 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 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 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 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 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 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 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 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 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 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 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 portab.h TransTable.h ../include/dll.h -Scheduler.o: Timer.h ABstats.h Moves.h Stats.h -SolveBoard.o: dds.h debug.h 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 portab.h TransTable.h ../include/dll.h Timer.h -SolverIF.o: ABstats.h Moves.h Stats.h Scheduler.h Init.h threadmem.h +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 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 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 portab.h TransTable.h ../include/dll.h Timer.h -TransTable.o: ABstats.h Moves.h Stats.h Scheduler.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 From ab093e8b93d5a89ed7cb442b540d8e0937b66255 Mon Sep 17 00:00:00 2001 From: Soren Hein Date: Sat, 6 Dec 2014 18:06:20 +0100 Subject: [PATCH 004/199] Bug fix: Scheduler wrongly found some hands to be identical The old test was rather heuristic and adequate for random distributions in a batch. But it was not good enough for distributions that are explicitly generated to be similar, such as distributions with two given hands (dummy and a defender) and other hands consistent with the bidding. The heuristic test is now better, and it is followed by a rigorous test among the remaining candidates. --- src/Scheduler.cpp | 57 +++++++++++++++++++++++++++++++++++++---------- src/Scheduler.h | 5 +++++ 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/Scheduler.cpp b/src/Scheduler.cpp index e37b4bd5..9252aa03 100644 --- a/src/Scheduler.cpp +++ b/src/Scheduler.cpp @@ -229,17 +229,21 @@ void Scheduler::MakeGroups( unsigned dlXor = dl->remainCards[0][0] ^ - dl->remainCards[0][1] ^ - dl->remainCards[0][2] ^ - dl->remainCards[0][3]; + dl->remainCards[1][1] ^ + dl->remainCards[2][2] ^ + dl->remainCards[3][3]; int key = static_cast(((dlXor >> 2) ^ (dlXor >> 6)) & 0x7f); hands[b].spareKey = static_cast( (dl->remainCards[1][0] << 17) ^ - (dl->remainCards[1][1] << 11) ^ - (dl->remainCards[1][2] << 5) ^ - (dl->remainCards[1][3] >> 2)); + (dl->remainCards[2][1] << 11) ^ + (dl->remainCards[3][2] << 5) ^ + (dl->remainCards[0][3] >> 2)); + + for (int h = 0; h < DDS_HANDS; h++) + for (int s = 0; s < DDS_SUITS; s++) + hands[b].remainCards[h][s] = dl->remainCards[h][s]; hands[b].NTflag = (strain == 4 ? 1 : 0); hands[b].first = dl->first; @@ -294,7 +298,19 @@ void Scheduler::FinetuneGroups() b1 = lp->first; b2 = hands[lp->first].next; + bool match = false; if (hands[b1].spareKey == hands[b2].spareKey) + { + // It is now extremely likely that it is a repeat hand, + // but we have to be sure. + match = true; + for (int h = 0; h < DDS_HANDS && match; h++) + for (int s = 0; s < DDS_SUITS && match; s++) + if (hands[b1].remainCards[h][s] != hands[b2].remainCards[h][s]) + match = false; + } + + if (match) continue; // Leave the first hand in place. @@ -334,7 +350,7 @@ void Scheduler::FinetuneGroups() index = hands[index].next; } - // Sort the list. + // Sort the list heuristically by spareKey value. for (int i = 1; i < sortLen; i++) { @@ -345,15 +361,19 @@ void Scheduler::FinetuneGroups() sortList[j] = st; } - if (sortList[0].value == sortList[sortLen - 1].value) - continue; - // First group stays where it is, but shorter and rejigged. + // From here on, hand comparisons are completely rigorous. + // We might miss duplicates, but we won't let different + // hands through as belonging to the same group. int l = 0; - while (l < sortLen && sortList[l].value == sortList[l + 1].value) + while (l < sortLen-1 && + Scheduler::SameHand(sortList[l].number, sortList[l+1].number)) l++; + if (l == sortLen-1) + continue; + lp->first = sortList[0].number; lp->last = sortList[l].number; lp->length = l + 1; @@ -373,7 +393,7 @@ void Scheduler::FinetuneGroups() while (l < sortLen) { - if (sortList[l].value == sortList[l - 1].value) + if (Scheduler::SameHand(sortList[l].number, sortList[l-1].number)) { // Same group int nOld = sortList[l - 1].number; @@ -408,6 +428,19 @@ void Scheduler::FinetuneGroups() } +bool Scheduler::SameHand( + int hno1, + int hno2) +{ + for (int h = 0; h < DDS_HANDS; h++) + for (int s = 0; s < DDS_SUITS; s++) + if (hands[hno1].remainCards[h][s] != hands[hno2].remainCards[h][s]) + return false; + + return true; +} + + // These are specific times from a 12-core PC. The hope is // that they scale somewhat proportionally to other cases. // The strength parameter is currently not used. diff --git a/src/Scheduler.h b/src/Scheduler.h index c4a1698f..9c381845 100644 --- a/src/Scheduler.h +++ b/src/Scheduler.h @@ -72,6 +72,7 @@ class Scheduler { int next; int spareKey; + unsigned remainCards[DDS_HANDS][DDS_SUITS]; int NTflag; int first; int strain; @@ -138,6 +139,10 @@ class Scheduler void FinetuneGroups(); + bool SameHand( + int hno1, + int hno2); + void SortSolve(), SortCalc(), SortTrace(); From 811c6ebdb87019e50fc9a7c0636e5721f58003f9 Mon Sep 17 00:00:00 2001 From: Soren Hein Date: Sat, 6 Dec 2014 18:25:21 +0100 Subject: [PATCH 005/199] Consistent #include guards without leading underscore, resolves #11 --- include/dll.h | 4 ++-- include/portab.h | 5 +++++ src/ABsearch.h | 4 ++++ src/ABstats.h | 5 ++--- src/Init.h | 5 +++++ src/LaterTricks.h | 5 +++++ src/Moves.h | 5 ++--- src/PBN.h | 4 ++++ src/QuickTricks.h | 4 ++++ src/Scheduler.h | 5 ++--- src/SolveBoard.h | 4 ++++ src/SolverIF.h | 4 ++++ src/Stats.h | 5 ++--- src/Timer.h | 6 +++--- src/TransTable.h | 5 ++--- src/dds.h | 5 ++--- src/debug.h | 4 ++++ src/threadmem.h | 5 ++--- 18 files changed, 58 insertions(+), 26 deletions(-) diff --git a/include/dll.h b/include/dll.h index 6a46076f..23bb4d90 100644 --- a/include/dll.h +++ b/include/dll.h @@ -8,8 +8,8 @@ */ -#ifndef DDS_DLLH -#define DDS_DLLH +#ifndef DDS_DLL_H +#define DDS_DLL_H #if defined(_WIN32) || defined(__CYGWIN__) #define DLLEXPORT __declspec(dllexport) diff --git a/include/portab.h b/include/portab.h index 89846aa3..53a69388 100644 --- a/include/portab.h +++ b/include/portab.h @@ -7,6 +7,9 @@ See LICENSE and README. */ +#ifndef DDS_PORTAB_H +#define DDS_PORTAB_H + #if defined(_WIN32) #if defined(__MINGW32__) && !defined(WINVER) @@ -69,3 +72,5 @@ #define nullptr NULL #endif #endif + +#endif diff --git a/src/ABsearch.h b/src/ABsearch.h index 66ab198d..160ff927 100644 --- a/src/ABsearch.h +++ b/src/ABsearch.h @@ -7,6 +7,9 @@ See LICENSE and README. */ +#ifndef DDS_ABSEARCH_H +#define DDS_ABSEARCH_H + #define DDS_POS_LINES 5 #define DDS_HAND_LINES 12 @@ -111,3 +114,4 @@ void RankToText( unsigned short int rankInSuit[DDS_HANDS][DDS_SUITS], char text[DDS_HAND_LINES][DDS_FULL_LINE]); +#endif diff --git a/src/ABstats.h b/src/ABstats.h index 6b85650d..c3e60d5d 100644 --- a/src/ABstats.h +++ b/src/ABstats.h @@ -7,9 +7,8 @@ See LICENSE and README. */ - -#ifndef _DDS_AB_STATS -#define _DDS_AB_STATS +#ifndef DDS_ABSTATS_H +#define DDS_ABSTATS_H #include #include diff --git a/src/Init.h b/src/Init.h index aca3d91d..9796a07f 100644 --- a/src/Init.h +++ b/src/Init.h @@ -7,6 +7,9 @@ See LICENSE and README. */ +#ifndef DDS_INIT_H +#define DDS_INIT_H + void SetDeal( struct localVarType * thrp); @@ -28,3 +31,5 @@ void CloseDebugFiles(); // Used by SH for stand-alone mode. void DDSidentify(char * s); + +#endif diff --git a/src/LaterTricks.h b/src/LaterTricks.h index 0f3f3c44..2a848b88 100644 --- a/src/LaterTricks.h +++ b/src/LaterTricks.h @@ -7,6 +7,9 @@ See LICENSE and README. */ +#ifndef DDS_LATERTRICKS_H +#define DDS_LATERTRICKS_H + bool LaterTricksMIN( struct pos * posPoint, @@ -23,3 +26,5 @@ bool LaterTricksMAX( int target, int trump, struct localVarType * thrp); + +#endif diff --git a/src/Moves.h b/src/Moves.h index e337cbd5..e2bb1cf1 100644 --- a/src/Moves.h +++ b/src/Moves.h @@ -7,9 +7,8 @@ See LICENSE and README. */ - -#ifndef _DDS_MOVES -#define _DDS_MOVES +#ifndef DDS_MOVES_H +#define DDS_MOVES_H #include #include diff --git a/src/PBN.h b/src/PBN.h index 6c92b184..e5c00a99 100644 --- a/src/PBN.h +++ b/src/PBN.h @@ -7,6 +7,9 @@ See LICENSE and README. */ +#ifndef DDS_PBN_H +#define DDS_PBN_H + int ConvertFromPBN( char * dealBuff, @@ -16,3 +19,4 @@ int ConvertPlayFromPBN( struct playTracePBN * playPBN, struct playTraceBin * playBin); +#endif diff --git a/src/QuickTricks.h b/src/QuickTricks.h index 09b7ecee..c6f85d02 100644 --- a/src/QuickTricks.h +++ b/src/QuickTricks.h @@ -7,6 +7,9 @@ See LICENSE and README. */ +#ifndef DDS_QUICKTRICKS_H +#define DDS_QUICKTRICKS_H + int QuickTricks( struct pos * posPoint, @@ -25,3 +28,4 @@ bool QuickTricksSecondHand( int trump, struct localVarType * thrp); +#endif diff --git a/src/Scheduler.h b/src/Scheduler.h index 9c381845..5ac31e95 100644 --- a/src/Scheduler.h +++ b/src/Scheduler.h @@ -7,9 +7,8 @@ See LICENSE and README. */ - -#ifndef _DDS_SCHEDULER -#define _DDS_SCHEDULER +#ifndef DDS_SCHEDULER_H +#define DDS_SCHEDULER_H #include #include diff --git a/src/SolveBoard.h b/src/SolveBoard.h index 69c391f1..ac56fdfc 100644 --- a/src/SolveBoard.h +++ b/src/SolveBoard.h @@ -7,6 +7,9 @@ See LICENSE and README. */ +#ifndef DDS_SOLVEBOARD_H +#define DDS_SOLVEBOARD_H + int SolveAllBoardsN( struct boards * bop, @@ -14,3 +17,4 @@ int SolveAllBoardsN( int chunkSize, int source); // 0 source, 1 calc +#endif diff --git a/src/SolverIF.h b/src/SolverIF.h index c30f9ded..b36dfcb9 100644 --- a/src/SolverIF.h +++ b/src/SolverIF.h @@ -7,6 +7,9 @@ See LICENSE and README. */ +#ifndef DDS_SOLVERIF_H +#define DDS_SOLVERIF_H + int SolveSameBoard( deal dl, @@ -22,3 +25,4 @@ int AnalyseLaterBoard( futureTricks * futp, int thrp); +#endif diff --git a/src/Stats.h b/src/Stats.h index 103ce5a3..691e2cd6 100644 --- a/src/Stats.h +++ b/src/Stats.h @@ -7,9 +7,8 @@ See LICENSE and README. */ - -#ifndef DDS_STATSH -#define DDS_STATSH +#ifndef DDS_STATS_H +#define DDS_STATS_H void InitTimer(); diff --git a/src/Timer.h b/src/Timer.h index f5914d67..d9f9a8c1 100644 --- a/src/Timer.h +++ b/src/Timer.h @@ -7,6 +7,9 @@ See LICENSE and README. */ +#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, @@ -35,9 +38,6 @@ */ -#ifndef _DDS_TIMING -#define _DDS_TIMING - #include #include #include diff --git a/src/TransTable.h b/src/TransTable.h index e7e44a47..18913d7b 100644 --- a/src/TransTable.h +++ b/src/TransTable.h @@ -7,6 +7,8 @@ See LICENSE and README. */ +#ifndef DDS_TRANSTABLES_H +#define DDS_TRANSTABLES_H /* This is an object for managing transposition tables and the @@ -14,9 +16,6 @@ */ -#ifndef _DDS_TRANSTABLES -#define _DDS_TRANSTABLES - #include #include #include diff --git a/src/dds.h b/src/dds.h index 35f31a3f..471c6139 100644 --- a/src/dds.h +++ b/src/dds.h @@ -7,9 +7,8 @@ See LICENSE and README. */ - -#ifndef DDS_DDSH -#define DDS_DDSH +#ifndef DDS_DDS_H +#define DDS_DDS_H #include #include diff --git a/src/debug.h b/src/debug.h index 027855bd..fe69d0cd 100644 --- a/src/debug.h +++ b/src/debug.h @@ -7,6 +7,9 @@ See LICENSE and README. */ +#ifndef DDS_DEBUG_H +#define DDS_DEBUG_H + /* A number of debug flags cause output files to be generated. @@ -140,3 +143,4 @@ extern long long counter[COUNTER_SLOTS]; +#endif diff --git a/src/threadmem.h b/src/threadmem.h index 2d076e88..7a83fcbb 100644 --- a/src/threadmem.h +++ b/src/threadmem.h @@ -7,9 +7,8 @@ See LICENSE and README. */ - -#ifndef DDS_THREADMEMH -#define DDS_DDSH +#ifndef DDS_THREADMEM_H +#define DDS_THREADMEM_H struct WinnerEntryType { From 2abfc9e378fb8e8ca799d5fe45aeabde7f3191ae Mon Sep 17 00:00:00 2001 From: Soren Hein Date: Sat, 6 Dec 2014 20:45:52 +0100 Subject: [PATCH 006/199] Added test to src Makefiles for existence of ../test and ../examples --- src/Makefiles/Makefile_Mac_clang | 2 ++ src/Makefiles/Makefile_Mac_gcc | 2 ++ src/Makefiles/Makefile_Visual | 2 ++ src/Makefiles/Makefile_cygwin | 2 ++ src/Makefiles/Makefile_linux | 2 ++ src/Makefiles/Makefile_linux_shared | 4 ++++ src/Makefiles/Makefile_mingw | 2 ++ 7 files changed, 16 insertions(+) diff --git a/src/Makefiles/Makefile_Mac_clang b/src/Makefiles/Makefile_Mac_clang index f0e93c89..3d3e21a4 100644 --- a/src/Makefiles/Makefile_Mac_clang +++ b/src/Makefiles/Makefile_Mac_clang @@ -81,6 +81,8 @@ 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 diff --git a/src/Makefiles/Makefile_Mac_gcc b/src/Makefiles/Makefile_Mac_gcc index 96d2f118..4a2be4c9 100644 --- a/src/Makefiles/Makefile_Mac_gcc +++ b/src/Makefiles/Makefile_Mac_gcc @@ -94,6 +94,8 @@ 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 diff --git a/src/Makefiles/Makefile_Visual b/src/Makefiles/Makefile_Visual index 35f079e0..1c59542e 100644 --- a/src/Makefiles/Makefile_Visual +++ b/src/Makefiles/Makefile_Visual @@ -93,6 +93,8 @@ clean: rm -f $(OBJ_FILES) $(DLL) $(DLLBASE).{lib,exp,def,obj,res} install: + test -d ../test || mkdir ../test + test -d ../examples || mkdir ../examples cp $(DLL) $(DLIB) ../test cp $(DLL) $(DLIB) ../examples diff --git a/src/Makefiles/Makefile_cygwin b/src/Makefiles/Makefile_cygwin index a43c5dcc..1ff71bb7 100644 --- a/src/Makefiles/Makefile_cygwin +++ b/src/Makefiles/Makefile_cygwin @@ -116,6 +116,8 @@ 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 diff --git a/src/Makefiles/Makefile_linux b/src/Makefiles/Makefile_linux index d856a67b..6cdc1ddb 100644 --- a/src/Makefiles/Makefile_linux +++ b/src/Makefiles/Makefile_linux @@ -93,6 +93,8 @@ 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 diff --git a/src/Makefiles/Makefile_linux_shared b/src/Makefiles/Makefile_linux_shared index 85da9492..9e7cd25f 100644 --- a/src/Makefiles/Makefile_linux_shared +++ b/src/Makefiles/Makefile_linux_shared @@ -102,6 +102,10 @@ 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 diff --git a/src/Makefiles/Makefile_mingw b/src/Makefiles/Makefile_mingw index 83c9ec13..cd1b0ee2 100644 --- a/src/Makefiles/Makefile_mingw +++ b/src/Makefiles/Makefile_mingw @@ -118,6 +118,8 @@ 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 From 6d10e4aca1d2615547ddf97b6639a3b88df6f743 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 08:48:21 +0100 Subject: [PATCH 007/199] First part of converting dds DOC to md --- doc/dll-description.md | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 doc/dll-description.md diff --git a/doc/dll-description.md b/doc/dll-description.md new file mode 100644 index 00000000..a8414f41 --- /dev/null +++ b/doc/dll-description.md @@ -0,0 +1,49 @@ +Bo Haglund, Bob Richardson +Rev V, 2014-10-14 +Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ + +# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +## Callable functions +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +Return codes are given at the end. + +Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! + +## The Basic Functions + +The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. + +### The Multi-Thread Double Dummy Solver Functions + +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. + +To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. + +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. + +The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. + +The call `FreeMemory` causes DDS to give up its dynamically allocated memory. + +### The PAR Calculation Functions + +The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. + +Two alternatives are given: + +1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. +2. The dealer hand is assumed to “start the bidding”. + +The presentation of the par score and contracts are given in alternative formats. + +The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. + +The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. + +It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. + +The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. + +### Double Dummy Value Analyser Functions + +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file From b14e286ce05e37a25600458c3b87fba70427e361 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 08:48:21 +0100 Subject: [PATCH 008/199] First part of converting dds DOC to md --- dds.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 dds.md diff --git a/dds.md b/dds.md new file mode 100644 index 00000000..a8414f41 --- /dev/null +++ b/dds.md @@ -0,0 +1,49 @@ +Bo Haglund, Bob Richardson +Rev V, 2014-10-14 +Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ + +# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +## Callable functions +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +Return codes are given at the end. + +Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! + +## The Basic Functions + +The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. + +### The Multi-Thread Double Dummy Solver Functions + +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. + +To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. + +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. + +The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. + +The call `FreeMemory` causes DDS to give up its dynamically allocated memory. + +### The PAR Calculation Functions + +The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. + +Two alternatives are given: + +1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. +2. The dealer hand is assumed to “start the bidding”. + +The presentation of the par score and contracts are given in alternative formats. + +The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. + +The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. + +It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. + +The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. + +### Double Dummy Value Analyser Functions + +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file From eeb392d470eee92c8ef7dead5acf8ace23746b14 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:09:33 +0100 Subject: [PATCH 009/199] First try at the big table in dss.md --- doc/dll-description.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index a8414f41..d6d7b6c7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -1,5 +1,7 @@ Bo Haglund, Bob Richardson + Rev V, 2014-10-14 + Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ # Description of the DLL functions supported in Double Dummy Problem Solver 2.7 @@ -46,4 +48,11 @@ The par calculation is executed using a single thread. But the calculation is ve ### Double Dummy Value Analyser Functions -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. + +------------------------------------------------------------------- +Function | Arguments | Format | Comment +------------------------------------------------------------------- +| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | +| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | + From 6794151388d50a243fa4a1607f1b460755af66fb Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:09:33 +0100 Subject: [PATCH 010/199] First try at the big table in dss.md --- dds.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dds.md b/dds.md index a8414f41..d6d7b6c7 100644 --- a/dds.md +++ b/dds.md @@ -1,5 +1,7 @@ Bo Haglund, Bob Richardson + Rev V, 2014-10-14 + Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ # Description of the DLL functions supported in Double Dummy Problem Solver 2.7 @@ -46,4 +48,11 @@ The par calculation is executed using a single thread. But the calculation is ve ### Double Dummy Value Analyser Functions -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. + +------------------------------------------------------------------- +Function | Arguments | Format | Comment +------------------------------------------------------------------- +| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | +| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | + From 052a90c960ae485c199e51ae99a74a5000d8e7bd Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:16:58 +0100 Subject: [PATCH 011/199] Second try at the big table in dss.md --- doc/dll-description.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index d6d7b6c7..7121c37d 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -51,8 +51,19 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. ------------------------------------------------------------------- -Function | Arguments | Format | Comment +Function | Arguments | Format | Comment | ------------------------------------------------------------------- -| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | -| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | Binary | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +------------------------------------------------------------------------ From 199198abecd4561e64b726fd3291f5ef93a4db75 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:16:58 +0100 Subject: [PATCH 012/199] Second try at the big table in dss.md --- dds.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/dds.md b/dds.md index d6d7b6c7..7121c37d 100644 --- a/dds.md +++ b/dds.md @@ -51,8 +51,19 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. ------------------------------------------------------------------- -Function | Arguments | Format | Comment +Function | Arguments | Format | Comment | ------------------------------------------------------------------- -| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | -| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | Binary | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +------------------------------------------------------------------------ From b16b5be977058d59e052774f07d0225feb0908f0 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:22:25 +0100 Subject: [PATCH 013/199] Third try at the big table in dss.md --- doc/dll-description.md | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 7121c37d..34bcd527 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,20 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -------------------------------------------------------------------- -Function | Arguments | Format | Comment | -------------------------------------------------------------------- -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | Binary | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | ------------------------------------------------------------------------- +| Function | Arguments | Format | Comment | +------------------|---------------------------|--------|---------------------------| +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | From 22b5f8df9b112c8a8167f165ed10fb8be66428bb Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:22:25 +0100 Subject: [PATCH 014/199] Third try at the big table in dss.md --- dds.md | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/dds.md b/dds.md index 7121c37d..34bcd527 100644 --- a/dds.md +++ b/dds.md @@ -50,20 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -------------------------------------------------------------------- -Function | Arguments | Format | Comment | -------------------------------------------------------------------- -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | Binary | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | ------------------------------------------------------------------------- +| Function | Arguments | Format | Comment | +------------------|---------------------------|--------|---------------------------| +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | From 513fb580316f54496de8ed9fcc6df77edb8ff41d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:37:48 +0100 Subject: [PATCH 015/199] Next try at the big table in dss.md, now with embedded HTL table --- doc/dll-description.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 34bcd527..5af61ad7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,18 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -| Function | Arguments | Format | Comment | -------------------|---------------------------|--------|---------------------------| -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | - + + + + + + + + + + + + + + +
FunctionArgumentsFormatComment
`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play
`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format.
\ No newline at end of file From c31f36fa2bf10eece25b963f65ff5e3a2d5e45c5 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:37:48 +0100 Subject: [PATCH 016/199] Next try at the big table in dss.md, now with embedded HTL table --- dds.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/dds.md b/dds.md index 34bcd527..5af61ad7 100644 --- a/dds.md +++ b/dds.md @@ -50,18 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -| Function | Arguments | Format | Comment | -------------------|---------------------------|--------|---------------------------| -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | - + + + + + + + + + + + + + + +
FunctionArgumentsFormatComment
`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play
`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format.
\ No newline at end of file From 25d0966ec17fae03c29887ca8fa57b6895eddb5d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:55:36 +0100 Subject: [PATCH 017/199] Still experimenting with HTML in mrkdown --- doc/dll-description.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 5af61ad7..54ef1a86 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,10 +58,10 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format. +`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. \ No newline at end of file From 8b35aa5a4c0b8c0a6d7070ffefedb8636aeccde8 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:55:36 +0100 Subject: [PATCH 018/199] Still experimenting with HTML in mrkdown --- dds.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dds.md b/dds.md index 5af61ad7..54ef1a86 100644 --- a/dds.md +++ b/dds.md @@ -58,10 +58,10 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format. +`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. \ No newline at end of file From 3dc86020dfc0f2d5565328e66deaf78d330bd38a Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:59:54 +0100 Subject: [PATCH 019/199] That was ugly. Next try --- doc/dll-description.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 54ef1a86..434dd758 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,10 +58,42 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + +int threadIndex + + +`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. + + +int target + + +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + + +int threadIndex \ No newline at end of file From a0a605ca6f11926472012d7f0449dc77f1156f56 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:59:54 +0100 Subject: [PATCH 020/199] That was ugly. Next try --- dds.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/dds.md b/dds.md index 54ef1a86..434dd758 100644 --- a/dds.md +++ b/dds.md @@ -58,10 +58,42 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + +int threadIndex + + +`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. + + +int target + + +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + + +int threadIndex \ No newline at end of file From d327d4b3e7e62bd5ce2b41ca005ebacbe0640bec Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:01:25 +0100 Subject: [PATCH 021/199] That was ugly. Next try --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 434dd758..105602d7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,7 +58,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play int target From 2ec859b14ff94b778bf1aeecbdc3dd3c6dda4d90 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:01:25 +0100 Subject: [PATCH 022/199] That was ugly. Next try --- dds.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 434dd758..105602d7 100644 --- a/dds.md +++ b/dds.md @@ -58,7 +58,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play int target From 1beba3997ff1c4c6bd42293c0ed69304052c5ef6 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:02:23 +0100 Subject: [PATCH 023/199] Much better now --- doc/dll-description.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 105602d7..11033a54 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -81,9 +81,6 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int target -int target - - int solutions From 61deabc019d04cac2ce96374959784b9962ee84a Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:02:23 +0100 Subject: [PATCH 024/199] Much better now --- dds.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/dds.md b/dds.md index 105602d7..11033a54 100644 --- a/dds.md +++ b/dds.md @@ -81,9 +81,6 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int target -int target - - int solutions From 990a6877b4ce2c0238132cb2d0cb5249aedfa190 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:27:49 +0100 Subject: [PATCH 025/199] Working examples --- doc/dll-description.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/dll-description.md b/doc/dll-description.md index 11033a54..23fac1dc 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,6 +50,7 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. + @@ -75,6 +76,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal + From 7d3d9edb2635479bcf25a12e43d488ec331b80f8 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:27:49 +0100 Subject: [PATCH 026/199] Working examples --- dds.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dds.md b/dds.md index 11033a54..23fac1dc 100644 --- a/dds.md +++ b/dds.md @@ -50,6 +50,7 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. +
int threadIndex
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
@@ -75,6 +76,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal + From befdf6d058a6635a545b310837b718c39dde9a30 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:29:32 +0100 Subject: [PATCH 027/199] Working on dds.md --- doc/dll-description.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 23fac1dc..884887d7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -77,7 +77,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + From 905f5224ddec626627b87254144686ed72a083c6 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:29:32 +0100 Subject: [PATCH 028/199] Working on dds.md --- dds.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dds.md b/dds.md index 23fac1dc..884887d7 100644 --- a/dds.md +++ b/dds.md @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -77,7 +77,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + From 6df3a7efc8dc7e0d6a793bfa8338dad2d86bd6d3 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 07:22:00 +0100 Subject: [PATCH 029/199] Added .gitignore --- doc/dll-description.md | 85 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 884887d7..f3ec539a 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -75,8 +75,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -94,5 +94,88 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +tr> + + + + + + + + +
int threadIndex
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later playSolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later playSolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int threadIndex
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format.
struct solvedBoards *solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
\ No newline at end of file From c90b3d446796ee6512c88447cf47cf6969ffa3a8 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 07:22:00 +0100 Subject: [PATCH 030/199] Added .gitignore --- dds.md | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 884887d7..f3ec539a 100644 --- a/dds.md +++ b/dds.md @@ -75,8 +75,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int threadIndex -   + SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. @@ -94,5 +94,88 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int threadIndex +  + +CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) + + +struct ddTableResults * tablep + +  + +CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. + + +struct ddTableResults * tablep + +  + +CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded. + + +int mode + + +int trumpFilter[5] + + +struct ddTablesRes *resp + + +struct allParResults *pres + +  + +CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format. + + +int mode + + +int trumpFilter[5] + + +struct ddTablesRes *resp + + +struct allParResults *pres + +  + +SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format. + + +struct solvedBoards *solvedp + +  + +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. + + +struct solvedBoards *solvedp + + +int chunkSize + +  + +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! + + +struct solvedBoards *solvedp + + +int chunkSize + +tr>  + +SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. + + +struct solvedBoards *solvedp + + +int chunkSize + \ No newline at end of file From f5af0973237ca9a069f859a0afc82a352222aa58 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Thu, 20 Nov 2014 08:18:29 +0100 Subject: [PATCH 031/199] All functiond described in dds.md --- doc/dll-description.md | 164 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 4 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index f3ec539a..a0d82343 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -149,7 +149,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! struct solvedBoards *solvedp @@ -169,7 +169,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal tr>  -SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -177,5 +177,161 @@ tr>  int chunkSize +  + +Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. + + +struct parResults *presp + + +int vulnerable + +  + +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. + + +struct parResultsDealer *presp + + +int dealer + + +int vulnerable + +  + +DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. + + +struct parResultsMaster * presp + + +int dealer + + +int vulnerable + +  + +ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. + + +char *resp + +  + +SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. + + +struct parResultsDealer *presp + + +int vulnerable + +  + +SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. + + +struct parResultsMaster sidesRes[2] + + +int vulnerable + +  + +ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. + + +char *resp + +  + +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! + + +int vulnerable + + +struct ddTableResults *tablep + + +struct parResults *presp + +  + +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! + + +struct ddTableResults *tablep + + +int vulnerable + + +struct parResults *presp + +  + +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. + + +struct playTraceBin play + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. + + +struct playTracePBN playPBN + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. + + +struct playTracesBin *plp + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. + + +struct playTracesPBN *plpPBN + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. + +  + +FreeMemoryvoidPBNFrees DDS allocated dynamical memory. + - \ No newline at end of file + From ad168f1e59bcb9a25b5a6aff3654c2b600a8b64e Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Thu, 20 Nov 2014 08:18:29 +0100 Subject: [PATCH 032/199] All functiond described in dds.md --- dds.md | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 160 insertions(+), 4 deletions(-) diff --git a/dds.md b/dds.md index f3ec539a..a0d82343 100644 --- a/dds.md +++ b/dds.md @@ -149,7 +149,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! struct solvedBoards *solvedp @@ -169,7 +169,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal tr>  -SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -177,5 +177,161 @@ tr>  int chunkSize +  + +Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. + + +struct parResults *presp + + +int vulnerable + +  + +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. + + +struct parResultsDealer *presp + + +int dealer + + +int vulnerable + +  + +DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. + + +struct parResultsMaster * presp + + +int dealer + + +int vulnerable + +  + +ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. + + +char *resp + +  + +SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. + + +struct parResultsDealer *presp + + +int vulnerable + +  + +SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. + + +struct parResultsMaster sidesRes[2] + + +int vulnerable + +  + +ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. + + +char *resp + +  + +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! + + +int vulnerable + + +struct ddTableResults *tablep + + +struct parResults *presp + +  + +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! + + +struct ddTableResults *tablep + + +int vulnerable + + +struct parResults *presp + +  + +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. + + +struct playTraceBin play + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. + + +struct playTracePBN playPBN + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. + + +struct playTracesBin *plp + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. + + +struct playTracesPBN *plpPBN + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. + +  + +FreeMemoryvoidPBNFrees DDS allocated dynamical memory. + - \ No newline at end of file + From 3608660588d0468bc0b2d7481e2fd0d9b2c6ecbd Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:46:58 +0100 Subject: [PATCH 033/199] Finished tables in dds.md --- doc/dll-description.md | 460 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) diff --git a/doc/dll-description.md b/doc/dll-description.md index a0d82343..7283e59e 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -335,3 +335,463 @@ tr>  +### Data sructure +Common encodings are as follows + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
+ + + + + + + + + + + +
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding PBN encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
+ + + + + + + + + + + +
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
+ + + + + + + + + + + +
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
+ + + + + + + + + + + + + + +
structFieldComment
parTextResultschar parText[2][128];
int equal;
+ + + + + + + + + + + + + + + + + +
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
+ + + + + + + + + + + + + + +
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
+ + + + + + + + + + + + + + +
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlayint number;
int tricks[53];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS / 10];
\ No newline at end of file From 64a8ede6d8c7cad633edd219b91f943c01f527d3 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:46:58 +0100 Subject: [PATCH 034/199] Finished tables in dds.md --- dds.md | 460 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) diff --git a/dds.md b/dds.md index a0d82343..7283e59e 100644 --- a/dds.md +++ b/dds.md @@ -335,3 +335,463 @@ tr>  +### Data sructure +Common encodings are as follows + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
+ + + + + + + + + + + +
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding PBN encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
+ + + + + + + + + + + +
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
+ + + + + + + + + + + +
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
+ + + + + + + + + + + + + + +
structFieldComment
parTextResultschar parText[2][128];
int equal;
+ + + + + + + + + + + + + + + + + +
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
+ + + + + + + + + + + + + + +
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
+ + + + + + + + + + + + + + +
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlayint number;
int tricks[53];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS / 10];
\ No newline at end of file From 94d8cee8dc188943886e6ed278c3e1507b8fadb1 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:59:06 +0100 Subject: [PATCH 035/199] Finished tables in dds.md --- doc/dll-description.md | 218 ++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 132 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 7283e59e..14cb1eae 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -415,15 +415,12 @@ Common encodings are as follows unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. - - - - + + + - - @@ -439,57 +436,49 @@ Common encodings are as follows - -
structFieldComment
dealPBNint trump;Suit encoding
char remainCards[80];Remaining cards. PBN encoding.
- - + + + + - - - -
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
- - + + + + - - @@ -505,15 +494,13 @@ Common encodings are as follows - -
structFieldComment
boardsint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + + - - @@ -529,15 +516,12 @@ Common encodings are as follows - -
structFieldComment
boardsPBNint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + - - @@ -556,84 +540,72 @@ Common encodings are as follows - -
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
- - + + + + - - - -
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
- - + + + + - - - -
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
- - + + + + - - - -
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
- - + + + + - - - -
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
- - + + + + - - @@ -643,15 +615,13 @@ Common encodings are as follows - -
structFieldComment
parResultsDealerint number;
char contracts[10][10];
- - + + + + - - @@ -661,15 +631,13 @@ Common encodings are as follows - -
structFieldComment
parResultsMasterint score;
struct contractType contracts[10];
- - + + + + - - @@ -685,30 +653,26 @@ Common encodings are as follows - -
structFieldComment
contractTypeint underTricks;
int seats;
- - + + + + - - - -
structFieldComment
parTextResultschar parText[2][128];
int equal;
- - + + + + - - @@ -718,75 +682,65 @@ Common encodings are as follows - -
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int rank[52];Encoding 2 .. 14 (not Card encoding).
- - + + + + - - - -
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
- - + + + + - - - -
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
solvedPlayint number;
int tricks[53];
- - + + + + - - From f382ef8e64e7cd1e48db6f4011adbe365484f2ca Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:59:06 +0100 Subject: [PATCH 036/199] Finished tables in dds.md --- dds.md | 218 +++++++++++++++++++++++---------------------------------- 1 file changed, 86 insertions(+), 132 deletions(-) diff --git a/dds.md b/dds.md index 7283e59e..14cb1eae 100644 --- a/dds.md +++ b/dds.md @@ -415,15 +415,12 @@ Common encodings are as follows - -
structFieldComment
solvedPlaysint noOfBoards;
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
- - + + + - - @@ -439,57 +436,49 @@ Common encodings are as follows - -
structFieldComment
dealPBNint trump;Suit encoding
char remainCards[80];Remaining cards. PBN encoding.
- - + + + + - - - -
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
- - + + + + - - @@ -505,15 +494,13 @@ Common encodings are as follows - -
structFieldComment
boardsint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + + - - @@ -529,15 +516,12 @@ Common encodings are as follows - -
structFieldComment
boardsPBNint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + - - @@ -556,84 +540,72 @@ Common encodings are as follows - -
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
- - + + + + - - - -
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
- - + + + + - - - -
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
- - + + + + - - - -
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
- - + + + + - - - -
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
- - + + + + - - @@ -643,15 +615,13 @@ Common encodings are as follows - -
structFieldComment
parResultsDealerint number;
char contracts[10][10];
- - + + + + - - @@ -661,15 +631,13 @@ Common encodings are as follows - -
structFieldComment
parResultsMasterint score;
struct contractType contracts[10];
- - + + + + - - @@ -685,30 +653,26 @@ Common encodings are as follows - -
structFieldComment
contractTypeint underTricks;
int seats;
- - + + + + - - - -
structFieldComment
parTextResultschar parText[2][128];
int equal;
- - + + + + - - @@ -718,75 +682,65 @@ Common encodings are as follows - -
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int rank[52];Encoding 2 .. 14 (not Card encoding).
- - + + + + - - - -
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
- - + + + + - - - -
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
solvedPlayint number;
int tricks[53];
- - + + + + - - From da7aef3fc65944800c4b907804c5e7176fc21ec2 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 01:40:49 +0100 Subject: [PATCH 037/199] Added a few pages --- doc/dll-description.md | 103 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 14cb1eae..a890c51c 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -748,4 +748,105 @@ Common encodings are as follows -
structFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS / 10];
\ No newline at end of file + + +### Functions + + + + + + + + + + + + + + + + + + + + + + + + + + +
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,
int threadIndexint threadIndex
+SolveBoardPBN is just like SolveBoard, except for the input format. + +SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. + +SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. + +There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. + +The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. + +For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
targetsolutionscomment
-11Find the maximum number of tricks for the side to +play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to +play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with +score set to 0.
02Return all cards that legal to play, with score set to +0.
1 .. 131If score is -1: Target cannot be reached.
+If score is 0: In fact no tricks at all can be won.
+If score is > 0: score will always equal target, even if more tricks can be won.
+One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
+If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
+“Reuse” means “reuse the transposition table from the previous run with the same thread number”. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. + +1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + From c1843c0c7f6a9bdd775c2342bbde394cc679b1fd Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 01:40:49 +0100 Subject: [PATCH 038/199] Added a few pages --- dds.md | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 14cb1eae..a890c51c 100644 --- a/dds.md +++ b/dds.md @@ -748,4 +748,105 @@ Common encodings are as follows struct solvedPlay solved[MAXNOOFBOARDS / 10]; - \ No newline at end of file + + +### Functions + + + + + + + + + + + + + + + + + + + + + + + + + + +
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,
int threadIndexint threadIndex
+SolveBoardPBN is just like SolveBoard, except for the input format. + +SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. + +SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. + +There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. + +The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. + +For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
targetsolutionscomment
-11Find the maximum number of tricks for the side to +play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to +play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with +score set to 0.
02Return all cards that legal to play, with score set to +0.
1 .. 131If score is -1: Target cannot be reached.
+If score is 0: In fact no tricks at all can be won.
+If score is > 0: score will always equal target, even if more tricks can be won.
+One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
+If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
+“Reuse” means “reuse the transposition table from the previous run with the same thread number”. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. + +1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + From 127d5c3f0bf7b6437157ce20cb2b811288c6d03d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 04:48:51 +0100 Subject: [PATCH 039/199] All text typed. --- doc/dll-description.md | 471 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 466 insertions(+), 5 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index a890c51c..c4887f0c 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -167,7 +167,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int chunkSize -tr>  +  SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. @@ -845,8 +845,469 @@ If the target cannot be achieved, only one card is returned with the score set a “Reuse” means “reuse the transposition table from the previous run with the same thread number”. For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. -1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` -2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` +1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` + +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` + +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + + + + + + + + + + + + + + + +
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults * tablepstruct ddTableResults * tablep
+CalcDDtablePBN is just like CalcDDtable, except for the input format. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. + + + + + + + + + + + + + + + + + + + + + + + + +
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *resp
struct allParResults *prespstruct allParResults *presp
+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. +The “mode” parameter contains the vulnerability (Vulnerable encoding) 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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + + + + + + + + + + + + + + + + + + + + + + + + +
Number of strainsMaximum number of DD tables
510
412
316
225
150
+ + + + + + + + + + + + + + + + + + +
SolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
+`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. +`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; +don’t use it. +The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +It is important to understand the parallelism and the concept of a chunk. +If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused +within a chunk. +No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: +* The same board is played at two tables of a team match. +* A board is played at 10 tables in a pairs tournament. +* The trump suit is the same, and there are very minor differences in the rest. +The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. +Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParDealerPar
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults *tablep 
struct parResultsDealer *sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster * prespstruct parResultsMaster * presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster *presstruct parResultsMaster *pres
char *respstruct parTextResults *resp
+The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. + +Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. + +The `vulnerable` parameter is given using Vulnerable encoding. + +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. + +The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. + +The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). + +In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. + +There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. + +Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: + +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,N 23H”: Only North makes 3 hearts. +* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. + +DealerPar() and SidesPar() give each par contract as a separate text string: + +* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. +* “3N-EW” means that E and W can both make exactly 3NT. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* SidesPar() give the par contract text strings as described above for each side. + +DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. + +After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. +Output example from ConvertToDealerTextFormat: + +“Par 110: NS 2S NS 2H” + +Output examples from ConvertToSidesTextFormat: + +“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. +”NS Par -120: W 2NT +EW Par 120: W 1NT+1” when it matters who starts the bidding. + + + + + + + + + + + + + + + + + + + + + +
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
+ +AnalysePlayPBN is just like AnalysePlayBin, except for the input format. + +The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. + +As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: + +9 10 10 10 10 9 9 + +The number of tricks are always seen from declarer’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. + + + + + + + + + + + + + + + + + + + + + +
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards *bopstruct boardsPBN *bopPBN
struct playTracesBin *plpstruct playTracesPBN *plpPBN
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
+AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. + +The AnalyseAllPlays* 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. + +Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. + + + + + + + + + + + + +
SetMaxThreadsFreeMemory
int userThreadsvoid
+SetMaxThreads returns the actual number of threads. + +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 threads 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. + +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. + +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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. + +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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. + +=== Return codes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a +different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. +Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +ConvertToDealerTextFormat, ConvertToSidesTextFormat
From 3fdd6029c4e8da0b3d3d134b5cccc0ba989d5e47 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 04:48:51 +0100 Subject: [PATCH 040/199] All text typed. --- dds.md | 471 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 466 insertions(+), 5 deletions(-) diff --git a/dds.md b/dds.md index a890c51c..c4887f0c 100644 --- a/dds.md +++ b/dds.md @@ -167,7 +167,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int chunkSize -tr>  +  SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. @@ -845,8 +845,469 @@ If the target cannot be achieved, only one card is returned with the score set a “Reuse” means “reuse the transposition table from the previous run with the same thread number”. For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. -1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` -2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` +1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` + +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` + +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + + + + + + + + + + + + + + + +
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults * tablepstruct ddTableResults * tablep
+CalcDDtablePBN is just like CalcDDtable, except for the input format. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. + + + + + + + + + + + + + + + + + + + + + + + + +
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *resp
struct allParResults *prespstruct allParResults *presp
+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. +The “mode” parameter contains the vulnerability (Vulnerable encoding) 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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + + + + + + + + + + + + + + + + + + + + + + + + +
Number of strainsMaximum number of DD tables
510
412
316
225
150
+ + + + + + + + + + + + + + + + + + +
SolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
+`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. +`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; +don’t use it. +The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +It is important to understand the parallelism and the concept of a chunk. +If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused +within a chunk. +No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: +* The same board is played at two tables of a team match. +* A board is played at 10 tables in a pairs tournament. +* The trump suit is the same, and there are very minor differences in the rest. +The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. +Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParDealerPar
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults *tablep 
struct parResultsDealer *sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster * prespstruct parResultsMaster * presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster *presstruct parResultsMaster *pres
char *respstruct parTextResults *resp
+The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. + +Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. + +The `vulnerable` parameter is given using Vulnerable encoding. + +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. + +The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. + +The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). + +In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. + +There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. + +Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: + +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,N 23H”: Only North makes 3 hearts. +* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. + +DealerPar() and SidesPar() give each par contract as a separate text string: + +* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. +* “3N-EW” means that E and W can both make exactly 3NT. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* SidesPar() give the par contract text strings as described above for each side. + +DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. + +After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. +Output example from ConvertToDealerTextFormat: + +“Par 110: NS 2S NS 2H” + +Output examples from ConvertToSidesTextFormat: + +“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. +”NS Par -120: W 2NT +EW Par 120: W 1NT+1” when it matters who starts the bidding. + + + + + + + + + + + + + + + + + + + + + +
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
+ +AnalysePlayPBN is just like AnalysePlayBin, except for the input format. + +The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. + +As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: + +9 10 10 10 10 9 9 + +The number of tricks are always seen from declarer’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. + + + + + + + + + + + + + + + + + + + + + +
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards *bopstruct boardsPBN *bopPBN
struct playTracesBin *plpstruct playTracesPBN *plpPBN
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
+AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. + +The AnalyseAllPlays* 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. + +Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. + + + + + + + + + + + + +
SetMaxThreadsFreeMemory
int userThreadsvoid
+SetMaxThreads returns the actual number of threads. + +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 threads 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. + +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. + +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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. + +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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. + +=== Return codes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a +different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. +Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +ConvertToDealerTextFormat, ConvertToSidesTextFormat
From a75c7651c8d721493ad3a729c3d605f4c0a19766 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 05:55:42 +0100 Subject: [PATCH 041/199] All changes made from diff. Document is now on par with v 2.8.0 --- doc/dll-description.md | 153 +++++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 59 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index c4887f0c..97a95458 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -1,31 +1,32 @@ -Bo Haglund, Bob Richardson +Bo Haglund, Soren Hein, Bob Richardson -Rev V, 2014-10-14 +Rev X, 2014-11-16 Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ -# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 ## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. + Return codes are given at the end. Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! ## The Basic Functions -The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. +The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. -The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. +The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. -The call `FreeMemory` causes DDS to give up its dynamically allocated memory. +Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. ### The PAR Calculation Functions @@ -142,7 +143,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format. +SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! struct solvedBoards *solvedp @@ -189,7 +190,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +of the dealer. struct parResultsDealer *presp @@ -327,12 +329,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) + +  + +FreeMemoryvoid Frees DDS allocated dynamical memory.   -FreeMemoryvoidPBNFrees DDS allocated dynamical memory. +ErrorMessageint code Turns a return code into an error message string. + + ### Data sructure @@ -413,7 +421,7 @@ Common encodings are as follows int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. +unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. @@ -454,10 +462,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTables;Number of DD table deals in structure +ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableDeal deals[MAXNOOFBOARDS/4]; +struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINS @@ -535,7 +543,7 @@ Common encodings are as follows int rank[13];Rank of the returned card. Value range 2-14. -int equals[13];Lower-ranked equals. Holding PBN encoding. +int equals[13];Lower-ranked equals. Holding encoding. int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks. @@ -558,7 +566,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. @@ -571,17 +579,17 @@ Common encodings are as follows structFieldComment -ddTablesResint noOfBoards; +ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableResults results[MAXNOOFBOARDS/4]; +struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINS -structFieldComment +StructFieldComment parResultschar parScore[2][16];First index is NS/EW. Side encoding. @@ -594,17 +602,17 @@ Common encodings are as follows -structFieldComment +StructFieldComment -allParResultsstruct parResults[MAXNOOFBOARDS/20]; +allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table -structFieldComment +StructFieldComment parResultsDealerint number; @@ -620,7 +628,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parResultsMasterint score; @@ -636,7 +644,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment contractTypeint underTricks; @@ -658,7 +666,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parTextResultschar parText[2][128]; @@ -671,7 +679,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -687,7 +695,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -700,7 +708,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesBinint noOfBoards; @@ -713,7 +721,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesPBNint noOfBoards; @@ -726,26 +734,26 @@ Common encodings are as follows -structFieldComment +StructFieldComment solvedPlayint number; -int tricks[53]; +int tricks[53];Starting position and up to 52 cards -structFieldComment +StructFieldComment solvedPlaysint noOfBoards; -struct solvedPlay solved[MAXNOOFBOARDS / 10]; +struct solvedPlay solved[MAXNOOFBOARDS]; @@ -778,10 +786,12 @@ Common encodings are as follows -SolveBoardPBN is just like SolveBoard, except for the input format. +SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. + SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. @@ -842,8 +852,11 @@ If the target cannot be achieved, only one card is returned with the score set a +Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, +and we may use it for something else in the future. If you think you need it, let us know! + “Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. 1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` @@ -896,10 +909,14 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy 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. -The “mode” parameter contains the vulnerability (Vulnerable encoding) for use in the par calculation. It is set to -1 if no par calculation is to be performed. + +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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + +The maximum number of DD tables in a CallAllTables call depends on the number of strains required, see the following table: @@ -909,19 +926,19 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + - + - +
510532
412440
316353
225280
1501160
@@ -929,15 +946,15 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + @@ -945,19 +962,20 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
SolverAllChunksBinSolveAllChunksPBNSolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bopstruct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. -`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; -don’t use it. + +`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. + The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. + It is important to understand the parallelism and the concept of a chunk. + If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused -within a chunk. -No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: -* The same board is played at two tables of a team match. -* A board is played at 10 tables in a pairs tournament. -* The trump suit is the same, and there are very minor differences in the rest. -The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. -Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. + +No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. + +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! @@ -1065,7 +1083,7 @@ Output example from ConvertToDealerTextFormat: Output examples from ConvertToSidesTextFormat: “NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT +”NS Par -120: W 2NT
EW Par 120: W 1NT+1” when it matters who starts the bidding.
@@ -1150,7 +1168,11 @@ DDS then checks whether a number of threads equal to the number of cores will fi 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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. +It may be possible, 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. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. + +It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. === Return codes
@@ -1204,6 +1226,17 @@ different number of boards in its first two arguments. + + + + + + + + + + + @@ -1309,5 +1342,7 @@ AnalyseAllPlaysPBN + +
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From 88ec01f9517180907f4890df3299eddcacc4c468 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 05:55:42 +0100 Subject: [PATCH 042/199] All changes made from diff. Document is now on par with v 2.8.0 --- dds.md | 153 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 94 insertions(+), 59 deletions(-) diff --git a/dds.md b/dds.md index c4887f0c..97a95458 100644 --- a/dds.md +++ b/dds.md @@ -1,31 +1,32 @@ -Bo Haglund, Bob Richardson +Bo Haglund, Soren Hein, Bob Richardson -Rev V, 2014-10-14 +Rev X, 2014-11-16 Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ -# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 ## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. + Return codes are given at the end. Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! ## The Basic Functions -The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. +The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. -The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. +The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. -The call `FreeMemory` causes DDS to give up its dynamically allocated memory. +Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. ### The PAR Calculation Functions @@ -142,7 +143,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format. +SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! struct solvedBoards *solvedp @@ -189,7 +190,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +of the dealer. struct parResultsDealer *presp @@ -327,12 +329,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) + +  + +FreeMemoryvoid Frees DDS allocated dynamical memory.   -FreeMemoryvoidPBNFrees DDS allocated dynamical memory. +ErrorMessageint code Turns a return code into an error message string. + + ### Data sructure @@ -413,7 +421,7 @@ Common encodings are as follows int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. +unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. @@ -454,10 +462,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTables;Number of DD table deals in structure +ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableDeal deals[MAXNOOFBOARDS/4]; +struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINS @@ -535,7 +543,7 @@ Common encodings are as follows int rank[13];Rank of the returned card. Value range 2-14. -int equals[13];Lower-ranked equals. Holding PBN encoding. +int equals[13];Lower-ranked equals. Holding encoding. int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks. @@ -558,7 +566,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. @@ -571,17 +579,17 @@ Common encodings are as follows structFieldComment -ddTablesResint noOfBoards; +ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableResults results[MAXNOOFBOARDS/4]; +struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINS -structFieldComment +StructFieldComment parResultschar parScore[2][16];First index is NS/EW. Side encoding. @@ -594,17 +602,17 @@ Common encodings are as follows -structFieldComment +StructFieldComment -allParResultsstruct parResults[MAXNOOFBOARDS/20]; +allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table -structFieldComment +StructFieldComment parResultsDealerint number; @@ -620,7 +628,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parResultsMasterint score; @@ -636,7 +644,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment contractTypeint underTricks; @@ -658,7 +666,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parTextResultschar parText[2][128]; @@ -671,7 +679,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -687,7 +695,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -700,7 +708,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesBinint noOfBoards; @@ -713,7 +721,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesPBNint noOfBoards; @@ -726,26 +734,26 @@ Common encodings are as follows -structFieldComment +StructFieldComment solvedPlayint number; -int tricks[53]; +int tricks[53];Starting position and up to 52 cards -structFieldComment +StructFieldComment solvedPlaysint noOfBoards; -struct solvedPlay solved[MAXNOOFBOARDS / 10]; +struct solvedPlay solved[MAXNOOFBOARDS]; @@ -778,10 +786,12 @@ Common encodings are as follows -SolveBoardPBN is just like SolveBoard, except for the input format. +SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. + SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. @@ -842,8 +852,11 @@ If the target cannot be achieved, only one card is returned with the score set a +Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, +and we may use it for something else in the future. If you think you need it, let us know! + “Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. 1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` @@ -896,10 +909,14 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy 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. -The “mode” parameter contains the vulnerability (Vulnerable encoding) for use in the par calculation. It is set to -1 if no par calculation is to be performed. + +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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + +The maximum number of DD tables in a CallAllTables call depends on the number of strains required, see the following table: @@ -909,19 +926,19 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + - + - +
510532
412440
316353
225280
1501160
@@ -929,15 +946,15 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + @@ -945,19 +962,20 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
SolverAllChunksBinSolveAllChunksPBNSolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bopstruct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. -`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; -don’t use it. + +`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. + The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. + It is important to understand the parallelism and the concept of a chunk. + If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused -within a chunk. -No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: -* The same board is played at two tables of a team match. -* A board is played at 10 tables in a pairs tournament. -* The trump suit is the same, and there are very minor differences in the rest. -The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. -Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. + +No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. + +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! @@ -1065,7 +1083,7 @@ Output example from ConvertToDealerTextFormat: Output examples from ConvertToSidesTextFormat: “NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT +”NS Par -120: W 2NT
EW Par 120: W 1NT+1” when it matters who starts the bidding.
@@ -1150,7 +1168,11 @@ DDS then checks whether a number of threads equal to the number of cores will fi 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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. +It may be possible, 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. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. + +It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. === Return codes
@@ -1204,6 +1226,17 @@ different number of boards in its first two arguments. + + + + + + + + + + + @@ -1309,5 +1342,7 @@ AnalyseAllPlaysPBN + +
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From cbf75d7f0a472441d9780a17660b97db99997a5b Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 07:56:46 +0100 Subject: [PATCH 043/199] Changes made focussing on Markup syntax --- doc/dll-description.md | 172 ++++++++++++++++++++++------------------- 1 file changed, 91 insertions(+), 81 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 97a95458..32bef118 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -18,7 +18,7 @@ The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand a ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. +The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. @@ -51,7 +51,6 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - @@ -72,7 +71,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -90,7 +89,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -100,18 +99,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -120,14 +119,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -136,65 +135,65 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - - + @@ -204,10 +203,10 @@ of the dealer. - + - + @@ -217,24 +216,24 @@ of the dealer. - + - + - + - + - + @@ -244,10 +243,10 @@ of the dealer. - + - + @@ -257,23 +256,23 @@ of the dealer. - + - + - + - + @@ -283,7 +282,7 @@ of the dealer. - + @@ -296,33 +295,33 @@ of the dealer. - + - + - + - + - + - + - + @@ -343,8 +342,10 @@ of the dealer.
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndex
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndexCalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded.SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *prespstruct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int dealer
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster * prespstruct parResultsMaster \* presp
int dealer
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char *respchar \*resp
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char *respchar \*resp
 
int vulnerable
struct ddTableResults *tablepstruct ddTableResults \*tablep
struct parResults *prespstruct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablepstruct ddTableResults \*tablep
int vulnerable
struct parResults *prespstruct parResults \*presp
 
struct playTraceBin play
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId struct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plpstruct playTracesBin \*plp
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBNstruct playTracesPBN \*plpPBN
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
-### Data sructure + +## Data structure Common encodings are as follows + @@ -465,7 +466,7 @@ Common encodings are as follows - + @@ -582,7 +583,7 @@ Common encodings are as follows - + @@ -758,7 +759,8 @@ Common encodings are as follows
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
-### Functions +## Functions + @@ -779,16 +781,17 @@ Common encodings are as follows - +
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
+ SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. -SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. @@ -852,6 +855,7 @@ If the target cannot be achieved, only one card is returned with the score set a + Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, and we may use it for something else in the future. If you think you need it, let us know! @@ -877,12 +881,13 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN -struct ddTableResults * tablepstruct ddTableResults * tablep +struct ddTableResults \* tablepstruct ddTableResults \* tablep + CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. @@ -892,7 +897,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + @@ -901,16 +906,17 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + - +
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealspstruct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint modeint trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *respstruct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults *prespstruct allParResults *prespstruct allParResults \*prespstruct allParResults \*presp
+ 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. +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. 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. @@ -951,21 +957,22 @@ The maximum number of DD tables in a CallAllTables call depends on the number of -struct boards *bopstruct boards *bopstruct boardsPBN *bop +struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop -struct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp +struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp int chunkSizeint chunkSize + `SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. `SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. -The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. It is important to understand the parallelism and the concept of a chunk. @@ -985,10 +992,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResults *prespstruct parResultsDealer *presp +struct parResults \*prespstruct parResultsDealer \*presp int vulnerableint dealer @@ -1003,10 +1010,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or Sidespar  -struct ddTableResults *tablep  +struct ddTableResults \*tablep  -struct parResultsDealer *sidesRes[2]  +struct parResultsDealer \*sidesRes[2]  int vulnerable  @@ -1018,10 +1025,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or DealerParBinSidesParBin -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResultsMaster * prespstruct parResultsMaster * presp +struct parResultsMaster \* prespstruct parResultsMaster \* presp int vulnerableint dealer @@ -1036,13 +1043,14 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or ConvertToDealerTextForamatConvertToSidesTextFormat -struct parResultsMaster *presstruct parResultsMaster *pres +struct parResultsMaster \*presstruct parResultsMaster \*pres -char *respstruct parTextResults *resp +char \*respstruct parTextResults \*resp + The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. @@ -1061,8 +1069,7 @@ There may be several par contracts, for instance 3NT just making and 5C just mak Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. * “NS:NS 23S,N 23H”: Only North makes 3 hearts. * “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. @@ -1070,7 +1077,7 @@ DealerPar() and SidesPar() give each par contract as a separate text string: * “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. * “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. * SidesPar() give the par contract text strings as described above for each side. DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. @@ -1100,7 +1107,7 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding. struct playTraceBin playstruct playTracePBN playPBN -struct solvedPlay *solvedpstruct solvedPlay *solvedp +struct solvedPlay \*solvedpstruct solvedPlay \*solvedp int thrIdint thrId @@ -1126,22 +1133,23 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one -struct boards *bopstruct boardsPBN *bopPBN +struct boards \*bopstruct boardsPBN \*bopPBN -struct playTracesBin *plpstruct playTracesPBN *plpPBN +struct playTracesBin \*plpstruct playTracesPBN \*plpPBN -struct solvedPlays *solvedpstruct solvedPlays *solvedp +struct solvedPlays \*solvedpstruct solvedPlays \*solvedp int chunkSizeint chunkSize + AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. -The AnalyseAllPlays* 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. +The AnalyseAllPlays\* 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. Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. @@ -1157,6 +1165,7 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi + SetMaxThreads returns the actual number of threads. 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 threads than there are processor cores, as this will only require more memory and will not improve performance. Within these constraints, DDS auto-configures the @@ -1174,7 +1183,8 @@ SetMaxThreads can be called multiple times even within the same session. So it i It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. -=== Return codes +## Return codes + @@ -1237,7 +1247,7 @@ different number of boards in its first two arguments. - @@ -1252,13 +1262,13 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + - + - +
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
From 516e1e6f00c4fe69cfb373253161f741715f21f4 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 07:56:46 +0100 Subject: [PATCH 044/199] Changes made focussing on Markup syntax --- dds.md | 172 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 91 insertions(+), 81 deletions(-) diff --git a/dds.md b/dds.md index 97a95458..32bef118 100644 --- a/dds.md +++ b/dds.md @@ -18,7 +18,7 @@ The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand a ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. +The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. @@ -51,7 +51,6 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - @@ -72,7 +71,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -90,7 +89,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -100,18 +99,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -120,14 +119,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -136,65 +135,65 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - - + @@ -204,10 +203,10 @@ of the dealer. - + - + @@ -217,24 +216,24 @@ of the dealer. - + - + - + - + - + @@ -244,10 +243,10 @@ of the dealer. - + - + @@ -257,23 +256,23 @@ of the dealer. - + - + - + - + @@ -283,7 +282,7 @@ of the dealer. - + @@ -296,33 +295,33 @@ of the dealer. - + - + - + - + - + - + - + @@ -343,8 +342,10 @@ of the dealer.
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndex
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndexCalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded.SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *prespstruct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int dealer
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster * prespstruct parResultsMaster \* presp
int dealer
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char *respchar \*resp
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char *respchar \*resp
 
int vulnerable
struct ddTableResults *tablepstruct ddTableResults \*tablep
struct parResults *prespstruct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablepstruct ddTableResults \*tablep
int vulnerable
struct parResults *prespstruct parResults \*presp
 
struct playTraceBin play
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId struct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plpstruct playTracesBin \*plp
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBNstruct playTracesPBN \*plpPBN
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
-### Data sructure + +## Data structure Common encodings are as follows + @@ -465,7 +466,7 @@ Common encodings are as follows - + @@ -582,7 +583,7 @@ Common encodings are as follows - + @@ -758,7 +759,8 @@ Common encodings are as follows
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
-### Functions +## Functions + @@ -779,16 +781,17 @@ Common encodings are as follows - +
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
+ SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. -SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. @@ -852,6 +855,7 @@ If the target cannot be achieved, only one card is returned with the score set a + Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, and we may use it for something else in the future. If you think you need it, let us know! @@ -877,12 +881,13 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN -struct ddTableResults * tablepstruct ddTableResults * tablep +struct ddTableResults \* tablepstruct ddTableResults \* tablep + CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. @@ -892,7 +897,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + @@ -901,16 +906,17 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + - +
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealspstruct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint modeint trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *respstruct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults *prespstruct allParResults *prespstruct allParResults \*prespstruct allParResults \*presp
+ 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. +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. 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. @@ -951,21 +957,22 @@ The maximum number of DD tables in a CallAllTables call depends on the number of -struct boards *bopstruct boards *bopstruct boardsPBN *bop +struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop -struct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp +struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp int chunkSizeint chunkSize + `SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. `SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. -The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. It is important to understand the parallelism and the concept of a chunk. @@ -985,10 +992,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResults *prespstruct parResultsDealer *presp +struct parResults \*prespstruct parResultsDealer \*presp int vulnerableint dealer @@ -1003,10 +1010,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or Sidespar  -struct ddTableResults *tablep  +struct ddTableResults \*tablep  -struct parResultsDealer *sidesRes[2]  +struct parResultsDealer \*sidesRes[2]  int vulnerable  @@ -1018,10 +1025,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or DealerParBinSidesParBin -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResultsMaster * prespstruct parResultsMaster * presp +struct parResultsMaster \* prespstruct parResultsMaster \* presp int vulnerableint dealer @@ -1036,13 +1043,14 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or ConvertToDealerTextForamatConvertToSidesTextFormat -struct parResultsMaster *presstruct parResultsMaster *pres +struct parResultsMaster \*presstruct parResultsMaster \*pres -char *respstruct parTextResults *resp +char \*respstruct parTextResults \*resp + The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. @@ -1061,8 +1069,7 @@ There may be several par contracts, for instance 3NT just making and 5C just mak Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. * “NS:NS 23S,N 23H”: Only North makes 3 hearts. * “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. @@ -1070,7 +1077,7 @@ DealerPar() and SidesPar() give each par contract as a separate text string: * “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. * “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. * SidesPar() give the par contract text strings as described above for each side. DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. @@ -1100,7 +1107,7 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding. struct playTraceBin playstruct playTracePBN playPBN -struct solvedPlay *solvedpstruct solvedPlay *solvedp +struct solvedPlay \*solvedpstruct solvedPlay \*solvedp int thrIdint thrId @@ -1126,22 +1133,23 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one -struct boards *bopstruct boardsPBN *bopPBN +struct boards \*bopstruct boardsPBN \*bopPBN -struct playTracesBin *plpstruct playTracesPBN *plpPBN +struct playTracesBin \*plpstruct playTracesPBN \*plpPBN -struct solvedPlays *solvedpstruct solvedPlays *solvedp +struct solvedPlays \*solvedpstruct solvedPlays \*solvedp int chunkSizeint chunkSize + AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. -The AnalyseAllPlays* 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. +The AnalyseAllPlays\* 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. Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. @@ -1157,6 +1165,7 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi + SetMaxThreads returns the actual number of threads. 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 threads than there are processor cores, as this will only require more memory and will not improve performance. Within these constraints, DDS auto-configures the @@ -1174,7 +1183,8 @@ SetMaxThreads can be called multiple times even within the same session. So it i It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. -=== Return codes +## Return codes + @@ -1237,7 +1247,7 @@ different number of boards in its first two arguments. - @@ -1252,13 +1262,13 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + - + - +
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
From f25462416dd2189836f727468b69a84d2f0a12a4 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 21:21:16 +0100 Subject: [PATCH 045/199] Extra commit before copying the file --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 32bef118..452d2ca3 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -22,7 +22,7 @@ The double dummy trick values for all 5 \* 4 = 20 possible combinations of a han To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. From e39dcdb0161fd364040d8b46f1e3026315cc2407 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 21:21:16 +0100 Subject: [PATCH 046/199] Extra commit before copying the file --- dds.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 32bef118..452d2ca3 100644 --- a/dds.md +++ b/dds.md @@ -22,7 +22,7 @@ The double dummy trick values for all 5 \* 4 = 20 possible combinations of a han To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. From f50b30423a77593459033b0e493dcffe9bd985a7 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 21:40:35 +0100 Subject: [PATCH 047/199] trying to get rid of dds.md --- dds.md | 1358 -------------------------------------------------------- 1 file changed, 1358 deletions(-) delete mode 100644 dds.md diff --git a/dds.md b/dds.md deleted file mode 100644 index 452d2ca3..00000000 --- a/dds.md +++ /dev/null @@ -1,1358 +0,0 @@ -Bo Haglund, Soren Hein, Bob Richardson - -Rev X, 2014-11-16 - -Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ - -# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 -## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. - -Return codes are given at the end. - -Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! - -## The Basic Functions - -The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. - -### The Multi-Thread Double Dummy Solver Functions - -The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. - -To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. - -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. - -The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. - -Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. - -### The PAR Calculation Functions - -The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. - -Two alternatives are given: - -1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. -2. The dealer hand is assumed to “start the bidding”. - -The presentation of the par score and contracts are given in alternative formats. - -The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. - -The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. - -It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. - -The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. - -### Double Dummy Value Analyser Functions - -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionArgumentsFormatComment
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge -of the dealer.
struct parResultsDealer \*presp
int dealer
int vulnerable
 
DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster \* presp
int dealer
int vulnerable
 
ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char \*resp
 
SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
int vulnerable
 
ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char \*resp
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTableResults \*tablep
struct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults \*tablep
int vulnerable
struct parResults \*presp
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
struct solvedPlay \*solvedp
int thrId
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
struct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin \*plp
struct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN \*plpPBN
struct solvedPlays \*solvedp
int chunkSize
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
ErrorMessageint code Turns a return code into an error message string.
-
- -## Data structure -Common encodings are as follows - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
StructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
StructFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
StructFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
StructFieldComment
parTextResultschar parText[2][128];
int equal;
StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
StructFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
StructFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
StructFieldComment
solvedPlayint number;
int tricks[53];Starting position and up to 52 cards
StructFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- -## Functions - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
- -SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. - -SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. - -If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. - -SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. - -There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. - -The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. - -For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
targetsolutionscomment
-11Find the maximum number of tricks for the side to -play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to -play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with -score set to 0.
02Return all cards that legal to play, with score set to -0.
1 .. 131If score is -1: Target cannot be reached.
-If score is 0: In fact no tricks at all can be won.
-If score is > 0: score will always equal target, even if more tricks can be won.
-One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
-If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
- -Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, -and we may use it for something else in the future. If you think you need it, let us know! - -“Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. - -1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` - -2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` - -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` - -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` - - - - - - - - - - - - - - - -
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablep
- -CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. - - - - - - - - - - - - - - - - - - - - - - - - -
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults \*prespstruct allParResults \*presp
- -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. - -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: - - - - - - - - - - - - - - - - - - - - - - - - -
Number of strainsMaximum number of DD tables
532
440
353
280
1160
- - - - - - - - - - - - - - - - - - -
SolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp
int chunkSizeint chunkSize
- -`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. - -`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. - -The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. - -It is important to understand the parallelism and the concept of a chunk. - -If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. - -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. - -No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. - -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! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResults \*prespstruct parResultsDealer \*presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults \*tablep 
struct parResultsDealer \*sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResultsMaster \* prespstruct parResultsMaster \* presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
char \*respstruct parTextResults \*resp
- -The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. - -Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. - -The `vulnerable` parameter is given using Vulnerable encoding. - -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. - -The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. - -The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). - -In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. - -There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. - -Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: - -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. -* “NS:NS 23S,N 23H”: Only North makes 3 hearts. -* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. - -DealerPar() and SidesPar() give each par contract as a separate text string: - -* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. -* “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. -* SidesPar() give the par contract text strings as described above for each side. - -DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. - -After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. -Output example from ConvertToDealerTextFormat: - -“Par 110: NS 2S NS 2H” - -Output examples from ConvertToSidesTextFormat: - -“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT
-EW Par 120: W 1NT+1” when it matters who starts the bidding. - - - - - - - - - - - - - - - - - - - - - -
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedp
int thrIdint thrId
- -AnalysePlayPBN is just like AnalysePlayBin, except for the input format. - -The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. - -As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: - -9 10 10 10 10 9 9 - -The number of tricks are always seen from declarer’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. - - - - - - - - - - - - - - - - - - - - - -
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedp
int chunkSizeint chunkSize
- -AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. - -The AnalyseAllPlays\* 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. - -Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. - - - - - - - - - - - - -
SetMaxThreadsFreeMemory
int userThreadsvoid
- -SetMaxThreads returns the actual number of threads. - -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 threads 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. - -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. - -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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. - -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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. - -It may be possible, 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. - -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. - -It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. - -## Return codes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a -different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) -Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. -Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, -AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, -ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From 289f15b46455a0e85e84b8c7aac24bd05a9ae6c2 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 21:40:35 +0100 Subject: [PATCH 048/199] trying to get rid of dds.md --- doc/dll-description.md | 1358 ---------------------------------------- 1 file changed, 1358 deletions(-) delete mode 100644 doc/dll-description.md diff --git a/doc/dll-description.md b/doc/dll-description.md deleted file mode 100644 index 452d2ca3..00000000 --- a/doc/dll-description.md +++ /dev/null @@ -1,1358 +0,0 @@ -Bo Haglund, Soren Hein, Bob Richardson - -Rev X, 2014-11-16 - -Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ - -# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 -## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. - -Return codes are given at the end. - -Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! - -## The Basic Functions - -The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. - -### The Multi-Thread Double Dummy Solver Functions - -The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. - -To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. - -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. - -The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. - -Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. - -### The PAR Calculation Functions - -The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. - -Two alternatives are given: - -1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. -2. The dealer hand is assumed to “start the bidding”. - -The presentation of the par score and contracts are given in alternative formats. - -The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. - -The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. - -It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. - -The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. - -### Double Dummy Value Analyser Functions - -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionArgumentsFormatComment
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge -of the dealer.
struct parResultsDealer \*presp
int dealer
int vulnerable
 
DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster \* presp
int dealer
int vulnerable
 
ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char \*resp
 
SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
int vulnerable
 
ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char \*resp
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTableResults \*tablep
struct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults \*tablep
int vulnerable
struct parResults \*presp
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
struct solvedPlay \*solvedp
int thrId
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
struct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin \*plp
struct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN \*plpPBN
struct solvedPlays \*solvedp
int chunkSize
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
ErrorMessageint code Turns a return code into an error message string.
-
- -## Data structure -Common encodings are as follows - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
StructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
StructFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
StructFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
StructFieldComment
parTextResultschar parText[2][128];
int equal;
StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
StructFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
StructFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
StructFieldComment
solvedPlayint number;
int tricks[53];Starting position and up to 52 cards
StructFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- -## Functions - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
- -SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. - -SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. - -If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. - -SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. - -There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. - -The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. - -For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
targetsolutionscomment
-11Find the maximum number of tricks for the side to -play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to -play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with -score set to 0.
02Return all cards that legal to play, with score set to -0.
1 .. 131If score is -1: Target cannot be reached.
-If score is 0: In fact no tricks at all can be won.
-If score is > 0: score will always equal target, even if more tricks can be won.
-One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
-If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
- -Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, -and we may use it for something else in the future. If you think you need it, let us know! - -“Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. - -1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` - -2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` - -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` - -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` - - - - - - - - - - - - - - - -
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablep
- -CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. - - - - - - - - - - - - - - - - - - - - - - - - -
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults \*prespstruct allParResults \*presp
- -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. - -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: - - - - - - - - - - - - - - - - - - - - - - - - -
Number of strainsMaximum number of DD tables
532
440
353
280
1160
- - - - - - - - - - - - - - - - - - -
SolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp
int chunkSizeint chunkSize
- -`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. - -`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. - -The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. - -It is important to understand the parallelism and the concept of a chunk. - -If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. - -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. - -No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. - -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! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResults \*prespstruct parResultsDealer \*presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults \*tablep 
struct parResultsDealer \*sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResultsMaster \* prespstruct parResultsMaster \* presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
char \*respstruct parTextResults \*resp
- -The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. - -Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. - -The `vulnerable` parameter is given using Vulnerable encoding. - -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. - -The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. - -The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). - -In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. - -There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. - -Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: - -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. -* “NS:NS 23S,N 23H”: Only North makes 3 hearts. -* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. - -DealerPar() and SidesPar() give each par contract as a separate text string: - -* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. -* “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. -* SidesPar() give the par contract text strings as described above for each side. - -DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. - -After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. -Output example from ConvertToDealerTextFormat: - -“Par 110: NS 2S NS 2H” - -Output examples from ConvertToSidesTextFormat: - -“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT
-EW Par 120: W 1NT+1” when it matters who starts the bidding. - - - - - - - - - - - - - - - - - - - - - -
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedp
int thrIdint thrId
- -AnalysePlayPBN is just like AnalysePlayBin, except for the input format. - -The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. - -As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: - -9 10 10 10 10 9 9 - -The number of tricks are always seen from declarer’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. - - - - - - - - - - - - - - - - - - - - - -
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedp
int chunkSizeint chunkSize
- -AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. - -The AnalyseAllPlays\* 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. - -Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. - - - - - - - - - - - - -
SetMaxThreadsFreeMemory
int userThreadsvoid
- -SetMaxThreads returns the actual number of threads. - -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 threads 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. - -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. - -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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. - -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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. - -It may be possible, 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. - -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. - -It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. - -## Return codes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a -different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) -Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. -Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, -AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, -ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From fbe0ede1acf7e29e0ad69e9189ae6d67d1e7009d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 08:48:21 +0100 Subject: [PATCH 049/199] First part of converting dds DOC to md --- dds.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 dds.md diff --git a/dds.md b/dds.md new file mode 100644 index 00000000..a8414f41 --- /dev/null +++ b/dds.md @@ -0,0 +1,49 @@ +Bo Haglund, Bob Richardson +Rev V, 2014-10-14 +Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ + +# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +## Callable functions +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +Return codes are given at the end. + +Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! + +## The Basic Functions + +The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. + +### The Multi-Thread Double Dummy Solver Functions + +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. + +To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. + +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. + +The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. + +The call `FreeMemory` causes DDS to give up its dynamically allocated memory. + +### The PAR Calculation Functions + +The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. + +Two alternatives are given: + +1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. +2. The dealer hand is assumed to “start the bidding”. + +The presentation of the par score and contracts are given in alternative formats. + +The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. + +The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. + +It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. + +The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. + +### Double Dummy Value Analyser Functions + +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file From 450deccf84bf63dfe50e3a7eb88146fc9714adfc Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 08:48:21 +0100 Subject: [PATCH 050/199] First part of converting dds DOC to md --- doc/dll-description.md | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 doc/dll-description.md diff --git a/doc/dll-description.md b/doc/dll-description.md new file mode 100644 index 00000000..a8414f41 --- /dev/null +++ b/doc/dll-description.md @@ -0,0 +1,49 @@ +Bo Haglund, Bob Richardson +Rev V, 2014-10-14 +Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ + +# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +## Callable functions +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +Return codes are given at the end. + +Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! + +## The Basic Functions + +The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. + +### The Multi-Thread Double Dummy Solver Functions + +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. + +To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. + +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. + +The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. + +The call `FreeMemory` causes DDS to give up its dynamically allocated memory. + +### The PAR Calculation Functions + +The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. + +Two alternatives are given: + +1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. +2. The dealer hand is assumed to “start the bidding”. + +The presentation of the par score and contracts are given in alternative formats. + +The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. + +The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. + +It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. + +The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. + +### Double Dummy Value Analyser Functions + +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file From 4a7131b796743dfabc34b0e91fb15d8f60784c31 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:09:33 +0100 Subject: [PATCH 051/199] First try at the big table in dss.md --- dds.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dds.md b/dds.md index a8414f41..d6d7b6c7 100644 --- a/dds.md +++ b/dds.md @@ -1,5 +1,7 @@ Bo Haglund, Bob Richardson + Rev V, 2014-10-14 + Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ # Description of the DLL functions supported in Double Dummy Problem Solver 2.7 @@ -46,4 +48,11 @@ The par calculation is executed using a single thread. But the calculation is ve ### Double Dummy Value Analyser Functions -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. + +------------------------------------------------------------------- +Function | Arguments | Format | Comment +------------------------------------------------------------------- +| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | +| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | + From 322354e2972956c656220582950f93609bf37219 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:09:33 +0100 Subject: [PATCH 052/199] First try at the big table in dss.md --- doc/dll-description.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index a8414f41..d6d7b6c7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -1,5 +1,7 @@ Bo Haglund, Bob Richardson + Rev V, 2014-10-14 + Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ # Description of the DLL functions supported in Double Dummy Problem Solver 2.7 @@ -46,4 +48,11 @@ The par calculation is executed using a single thread. But the calculation is ve ### Double Dummy Value Analyser Functions -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. + +------------------------------------------------------------------- +Function | Arguments | Format | Comment +------------------------------------------------------------------- +| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | +| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | + From 6dcd64767ecb40d52fdd34047fdd1c6cf4d68e8b Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:16:58 +0100 Subject: [PATCH 053/199] Second try at the big table in dss.md --- dds.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/dds.md b/dds.md index d6d7b6c7..7121c37d 100644 --- a/dds.md +++ b/dds.md @@ -51,8 +51,19 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. ------------------------------------------------------------------- -Function | Arguments | Format | Comment +Function | Arguments | Format | Comment | ------------------------------------------------------------------- -| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | -| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | Binary | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +------------------------------------------------------------------------ From 784f5b4bef5bb65aa5f0a00e05721b2e9b0cb755 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:16:58 +0100 Subject: [PATCH 054/199] Second try at the big table in dss.md --- doc/dll-description.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index d6d7b6c7..7121c37d 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -51,8 +51,19 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. ------------------------------------------------------------------- -Function | Arguments | Format | Comment +Function | Arguments | Format | Comment | ------------------------------------------------------------------- -| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | -| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | Binary | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +------------------------------------------------------------------------ From b07d81bf875488a15ee5af3c1d8cc64c386900f6 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:22:25 +0100 Subject: [PATCH 055/199] Third try at the big table in dss.md --- dds.md | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/dds.md b/dds.md index 7121c37d..34bcd527 100644 --- a/dds.md +++ b/dds.md @@ -50,20 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -------------------------------------------------------------------- -Function | Arguments | Format | Comment | -------------------------------------------------------------------- -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | Binary | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | ------------------------------------------------------------------------- +| Function | Arguments | Format | Comment | +------------------|---------------------------|--------|---------------------------| +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | From 2e6322f8d0c3c66c969dc2c85dd98475f77f67c1 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:22:25 +0100 Subject: [PATCH 056/199] Third try at the big table in dss.md --- doc/dll-description.md | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 7121c37d..34bcd527 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,20 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -------------------------------------------------------------------- -Function | Arguments | Format | Comment | -------------------------------------------------------------------- -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | Binary | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | ------------------------------------------------------------------------- +| Function | Arguments | Format | Comment | +------------------|---------------------------|--------|---------------------------| +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | From 35882e20e39bc7a4ac562c3794b69ab758f71ff0 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:37:48 +0100 Subject: [PATCH 057/199] Next try at the big table in dss.md, now with embedded HTL table --- dds.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/dds.md b/dds.md index 34bcd527..5af61ad7 100644 --- a/dds.md +++ b/dds.md @@ -50,18 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -| Function | Arguments | Format | Comment | -------------------|---------------------------|--------|---------------------------| -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | - + + + + + + + + + + + + + + +
FunctionArgumentsFormatComment
`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play
`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format.
\ No newline at end of file From b76142959409bbc26eb3df30a4168cbd40962419 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:37:48 +0100 Subject: [PATCH 058/199] Next try at the big table in dss.md, now with embedded HTL table --- doc/dll-description.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 34bcd527..5af61ad7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,18 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -| Function | Arguments | Format | Comment | -------------------|---------------------------|--------|---------------------------| -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | - + + + + + + + + + + + + + + +
FunctionArgumentsFormatComment
`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play
`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format.
\ No newline at end of file From b0e889ce72e32ede936976d0ecf602e4b75eb7db Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:55:36 +0100 Subject: [PATCH 059/199] Still experimenting with HTML in mrkdown --- dds.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dds.md b/dds.md index 5af61ad7..54ef1a86 100644 --- a/dds.md +++ b/dds.md @@ -58,10 +58,10 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format. +`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. \ No newline at end of file From e16daa70df1a5e1cae381744ec1f888e5f17c1b3 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:55:36 +0100 Subject: [PATCH 060/199] Still experimenting with HTML in mrkdown --- doc/dll-description.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 5af61ad7..54ef1a86 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,10 +58,10 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format. +`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. \ No newline at end of file From caccd91721babec5924cd742a69231aa7d49346d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:59:54 +0100 Subject: [PATCH 061/199] That was ugly. Next try --- dds.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/dds.md b/dds.md index 54ef1a86..434dd758 100644 --- a/dds.md +++ b/dds.md @@ -58,10 +58,42 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + +int threadIndex + + +`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. + + +int target + + +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + + +int threadIndex \ No newline at end of file From 9b13c65db33e9076f7540504f58d795da8cf29b5 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:59:54 +0100 Subject: [PATCH 062/199] That was ugly. Next try --- doc/dll-description.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 54ef1a86..434dd758 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,10 +58,42 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + +int threadIndex + + +`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. + + +int target + + +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + + +int threadIndex \ No newline at end of file From c3748efa181e76177a8febee3f302808cbed2056 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:01:25 +0100 Subject: [PATCH 063/199] That was ugly. Next try --- dds.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 434dd758..105602d7 100644 --- a/dds.md +++ b/dds.md @@ -58,7 +58,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play int target From b245f73b81cecb770e6fb0431bc1f6902e664063 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:01:25 +0100 Subject: [PATCH 064/199] That was ugly. Next try --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 434dd758..105602d7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,7 +58,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play int target From a97eb1e82f751a833c3cd21d1cb2c5e3f5d3f343 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:02:23 +0100 Subject: [PATCH 065/199] Much better now --- dds.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/dds.md b/dds.md index 105602d7..11033a54 100644 --- a/dds.md +++ b/dds.md @@ -81,9 +81,6 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int target -int target - - int solutions From 40b3c40fdd38a8d6e66bc70cbab7c837d21fcf57 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:02:23 +0100 Subject: [PATCH 066/199] Much better now --- doc/dll-description.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 105602d7..11033a54 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -81,9 +81,6 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int target -int target - - int solutions From e3918da09cf7cb27644b6bf9ecaf376de234ab3a Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:27:49 +0100 Subject: [PATCH 067/199] Working examples --- dds.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dds.md b/dds.md index 11033a54..23fac1dc 100644 --- a/dds.md +++ b/dds.md @@ -50,6 +50,7 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. + @@ -75,6 +76,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal + From ba3df3fa3704e493156b2e9cb78a6a315de6b098 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:27:49 +0100 Subject: [PATCH 068/199] Working examples --- doc/dll-description.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/dll-description.md b/doc/dll-description.md index 11033a54..23fac1dc 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,6 +50,7 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. +
int threadIndex
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
@@ -75,6 +76,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal + From 31e8a58a423f0932a9a13fa6c9d749dd390e2c8f Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:29:32 +0100 Subject: [PATCH 069/199] Working on dds.md --- dds.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dds.md b/dds.md index 23fac1dc..884887d7 100644 --- a/dds.md +++ b/dds.md @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -77,7 +77,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + From 655b14f66610bdfdfad6324d54e91bb66272ca38 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:29:32 +0100 Subject: [PATCH 070/199] Working on dds.md --- doc/dll-description.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 23fac1dc..884887d7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -77,7 +77,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + From b31fe2810066728abc709bf6d4c8085a8cf1f405 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 07:22:00 +0100 Subject: [PATCH 071/199] Added .gitignore --- dds.md | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 884887d7..f3ec539a 100644 --- a/dds.md +++ b/dds.md @@ -75,8 +75,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -94,5 +94,88 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +tr> + + + + + + + + +
int threadIndex
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later playSolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later playSolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int threadIndex
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format.
struct solvedBoards *solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
\ No newline at end of file From 7039cc24f485276ddddf6fa8948b1a9fc7187755 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 07:22:00 +0100 Subject: [PATCH 072/199] Added .gitignore --- doc/dll-description.md | 85 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 884887d7..f3ec539a 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -75,8 +75,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int threadIndex -   + SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. @@ -94,5 +94,88 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int threadIndex +  + +CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) + + +struct ddTableResults * tablep + +  + +CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. + + +struct ddTableResults * tablep + +  + +CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded. + + +int mode + + +int trumpFilter[5] + + +struct ddTablesRes *resp + + +struct allParResults *pres + +  + +CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format. + + +int mode + + +int trumpFilter[5] + + +struct ddTablesRes *resp + + +struct allParResults *pres + +  + +SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format. + + +struct solvedBoards *solvedp + +  + +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. + + +struct solvedBoards *solvedp + + +int chunkSize + +  + +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! + + +struct solvedBoards *solvedp + + +int chunkSize + +tr>  + +SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. + + +struct solvedBoards *solvedp + + +int chunkSize + \ No newline at end of file From a6df7282d1d58c5da77e786d350a1238a727bd89 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Thu, 20 Nov 2014 08:18:29 +0100 Subject: [PATCH 073/199] All functiond described in dds.md --- dds.md | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 160 insertions(+), 4 deletions(-) diff --git a/dds.md b/dds.md index f3ec539a..a0d82343 100644 --- a/dds.md +++ b/dds.md @@ -149,7 +149,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! struct solvedBoards *solvedp @@ -169,7 +169,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal tr>  -SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -177,5 +177,161 @@ tr>  int chunkSize +  + +Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. + + +struct parResults *presp + + +int vulnerable + +  + +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. + + +struct parResultsDealer *presp + + +int dealer + + +int vulnerable + +  + +DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. + + +struct parResultsMaster * presp + + +int dealer + + +int vulnerable + +  + +ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. + + +char *resp + +  + +SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. + + +struct parResultsDealer *presp + + +int vulnerable + +  + +SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. + + +struct parResultsMaster sidesRes[2] + + +int vulnerable + +  + +ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. + + +char *resp + +  + +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! + + +int vulnerable + + +struct ddTableResults *tablep + + +struct parResults *presp + +  + +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! + + +struct ddTableResults *tablep + + +int vulnerable + + +struct parResults *presp + +  + +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. + + +struct playTraceBin play + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. + + +struct playTracePBN playPBN + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. + + +struct playTracesBin *plp + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. + + +struct playTracesPBN *plpPBN + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. + +  + +FreeMemoryvoidPBNFrees DDS allocated dynamical memory. + - \ No newline at end of file + From 7bdf79ee75c323a0861752d1998e699fb99234e9 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Thu, 20 Nov 2014 08:18:29 +0100 Subject: [PATCH 074/199] All functiond described in dds.md --- doc/dll-description.md | 164 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 4 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index f3ec539a..a0d82343 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -149,7 +149,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! struct solvedBoards *solvedp @@ -169,7 +169,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal tr>  -SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -177,5 +177,161 @@ tr>  int chunkSize +  + +Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. + + +struct parResults *presp + + +int vulnerable + +  + +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. + + +struct parResultsDealer *presp + + +int dealer + + +int vulnerable + +  + +DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. + + +struct parResultsMaster * presp + + +int dealer + + +int vulnerable + +  + +ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. + + +char *resp + +  + +SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. + + +struct parResultsDealer *presp + + +int vulnerable + +  + +SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. + + +struct parResultsMaster sidesRes[2] + + +int vulnerable + +  + +ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. + + +char *resp + +  + +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! + + +int vulnerable + + +struct ddTableResults *tablep + + +struct parResults *presp + +  + +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! + + +struct ddTableResults *tablep + + +int vulnerable + + +struct parResults *presp + +  + +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. + + +struct playTraceBin play + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. + + +struct playTracePBN playPBN + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. + + +struct playTracesBin *plp + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. + + +struct playTracesPBN *plpPBN + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. + +  + +FreeMemoryvoidPBNFrees DDS allocated dynamical memory. + - \ No newline at end of file + From 677661ae92888bcb762dd8d5e9f975ef5de0f381 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:46:58 +0100 Subject: [PATCH 075/199] Finished tables in dds.md --- dds.md | 460 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) diff --git a/dds.md b/dds.md index a0d82343..7283e59e 100644 --- a/dds.md +++ b/dds.md @@ -335,3 +335,463 @@ tr>  +### Data sructure +Common encodings are as follows + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
+ + + + + + + + + + + +
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding PBN encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
+ + + + + + + + + + + +
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
+ + + + + + + + + + + +
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
+ + + + + + + + + + + + + + +
structFieldComment
parTextResultschar parText[2][128];
int equal;
+ + + + + + + + + + + + + + + + + +
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
+ + + + + + + + + + + + + + +
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
+ + + + + + + + + + + + + + +
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlayint number;
int tricks[53];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS / 10];
\ No newline at end of file From 760f67c571a420957755668e277e445083b0fbd6 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:46:58 +0100 Subject: [PATCH 076/199] Finished tables in dds.md --- doc/dll-description.md | 460 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) diff --git a/doc/dll-description.md b/doc/dll-description.md index a0d82343..7283e59e 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -335,3 +335,463 @@ tr>  +### Data sructure +Common encodings are as follows + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
+ + + + + + + + + + + +
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding PBN encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
+ + + + + + + + + + + +
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
+ + + + + + + + + + + +
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
+ + + + + + + + + + + + + + +
structFieldComment
parTextResultschar parText[2][128];
int equal;
+ + + + + + + + + + + + + + + + + +
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
+ + + + + + + + + + + + + + +
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
+ + + + + + + + + + + + + + +
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlayint number;
int tricks[53];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS / 10];
\ No newline at end of file From 10742b4482c37ea48adfc286ac1818f60c8154fe Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:59:06 +0100 Subject: [PATCH 077/199] Finished tables in dds.md --- dds.md | 218 +++++++++++++++++++++++---------------------------------- 1 file changed, 86 insertions(+), 132 deletions(-) diff --git a/dds.md b/dds.md index 7283e59e..14cb1eae 100644 --- a/dds.md +++ b/dds.md @@ -415,15 +415,12 @@ Common encodings are as follows unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. - - - - + + + - - @@ -439,57 +436,49 @@ Common encodings are as follows - -
structFieldComment
dealPBNint trump;Suit encoding
char remainCards[80];Remaining cards. PBN encoding.
- - + + + + - - - -
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
- - + + + + - - @@ -505,15 +494,13 @@ Common encodings are as follows - -
structFieldComment
boardsint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + + - - @@ -529,15 +516,12 @@ Common encodings are as follows - -
structFieldComment
boardsPBNint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + - - @@ -556,84 +540,72 @@ Common encodings are as follows - -
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
- - + + + + - - - -
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
- - + + + + - - - -
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
- - + + + + - - - -
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
- - + + + + - - - -
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
- - + + + + - - @@ -643,15 +615,13 @@ Common encodings are as follows - -
structFieldComment
parResultsDealerint number;
char contracts[10][10];
- - + + + + - - @@ -661,15 +631,13 @@ Common encodings are as follows - -
structFieldComment
parResultsMasterint score;
struct contractType contracts[10];
- - + + + + - - @@ -685,30 +653,26 @@ Common encodings are as follows - -
structFieldComment
contractTypeint underTricks;
int seats;
- - + + + + - - - -
structFieldComment
parTextResultschar parText[2][128];
int equal;
- - + + + + - - @@ -718,75 +682,65 @@ Common encodings are as follows - -
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int rank[52];Encoding 2 .. 14 (not Card encoding).
- - + + + + - - - -
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
- - + + + + - - - -
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
solvedPlayint number;
int tricks[53];
- - + + + + - - From 7404de4097fd53fa01aa038ae96a2d85a6a25007 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:59:06 +0100 Subject: [PATCH 078/199] Finished tables in dds.md --- doc/dll-description.md | 218 ++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 132 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 7283e59e..14cb1eae 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -415,15 +415,12 @@ Common encodings are as follows - -
structFieldComment
solvedPlaysint noOfBoards;
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
- - + + + - - @@ -439,57 +436,49 @@ Common encodings are as follows - -
structFieldComment
dealPBNint trump;Suit encoding
char remainCards[80];Remaining cards. PBN encoding.
- - + + + + - - - -
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
- - + + + + - - @@ -505,15 +494,13 @@ Common encodings are as follows - -
structFieldComment
boardsint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + + - - @@ -529,15 +516,12 @@ Common encodings are as follows - -
structFieldComment
boardsPBNint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + - - @@ -556,84 +540,72 @@ Common encodings are as follows - -
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
- - + + + + - - - -
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
- - + + + + - - - -
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
- - + + + + - - - -
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
- - + + + + - - - -
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
- - + + + + - - @@ -643,15 +615,13 @@ Common encodings are as follows - -
structFieldComment
parResultsDealerint number;
char contracts[10][10];
- - + + + + - - @@ -661,15 +631,13 @@ Common encodings are as follows - -
structFieldComment
parResultsMasterint score;
struct contractType contracts[10];
- - + + + + - - @@ -685,30 +653,26 @@ Common encodings are as follows - -
structFieldComment
contractTypeint underTricks;
int seats;
- - + + + + - - - -
structFieldComment
parTextResultschar parText[2][128];
int equal;
- - + + + + - - @@ -718,75 +682,65 @@ Common encodings are as follows - -
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int rank[52];Encoding 2 .. 14 (not Card encoding).
- - + + + + - - - -
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
- - + + + + - - - -
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
solvedPlayint number;
int tricks[53];
- - + + + + - - From 0a36518a54407749133ec1624ad59aa452940718 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 01:40:49 +0100 Subject: [PATCH 079/199] Added a few pages --- dds.md | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 14cb1eae..a890c51c 100644 --- a/dds.md +++ b/dds.md @@ -748,4 +748,105 @@ Common encodings are as follows -
structFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS / 10];
\ No newline at end of file + + +### Functions + + + + + + + + + + + + + + + + + + + + + + + + + + +
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,
int threadIndexint threadIndex
+SolveBoardPBN is just like SolveBoard, except for the input format. + +SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. + +SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. + +There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. + +The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. + +For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
targetsolutionscomment
-11Find the maximum number of tricks for the side to +play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to +play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with +score set to 0.
02Return all cards that legal to play, with score set to +0.
1 .. 131If score is -1: Target cannot be reached.
+If score is 0: In fact no tricks at all can be won.
+If score is > 0: score will always equal target, even if more tricks can be won.
+One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
+If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
+“Reuse” means “reuse the transposition table from the previous run with the same thread number”. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. + +1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + From 3221a7a80495a251f431d8b110eba98e9ef434dd Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 01:40:49 +0100 Subject: [PATCH 080/199] Added a few pages --- doc/dll-description.md | 103 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 14cb1eae..a890c51c 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -748,4 +748,105 @@ Common encodings are as follows struct solvedPlay solved[MAXNOOFBOARDS / 10]; - \ No newline at end of file + + +### Functions + + + + + + + + + + + + + + + + + + + + + + + + + + +
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,
int threadIndexint threadIndex
+SolveBoardPBN is just like SolveBoard, except for the input format. + +SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. + +SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. + +There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. + +The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. + +For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
targetsolutionscomment
-11Find the maximum number of tricks for the side to +play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to +play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with +score set to 0.
02Return all cards that legal to play, with score set to +0.
1 .. 131If score is -1: Target cannot be reached.
+If score is 0: In fact no tricks at all can be won.
+If score is > 0: score will always equal target, even if more tricks can be won.
+One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
+If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
+“Reuse” means “reuse the transposition table from the previous run with the same thread number”. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. + +1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + From 94ca35ea7e74ef4f7c73401b55bfdca245b35d3b Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 04:48:51 +0100 Subject: [PATCH 081/199] All text typed. --- dds.md | 471 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 466 insertions(+), 5 deletions(-) diff --git a/dds.md b/dds.md index a890c51c..c4887f0c 100644 --- a/dds.md +++ b/dds.md @@ -167,7 +167,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int chunkSize -tr>  +  SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. @@ -845,8 +845,469 @@ If the target cannot be achieved, only one card is returned with the score set a “Reuse” means “reuse the transposition table from the previous run with the same thread number”. For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. -1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` -2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` +1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` + +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` + +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + + + + + + + + + + + + + + + +
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults * tablepstruct ddTableResults * tablep
+CalcDDtablePBN is just like CalcDDtable, except for the input format. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. + + + + + + + + + + + + + + + + + + + + + + + + +
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *resp
struct allParResults *prespstruct allParResults *presp
+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. +The “mode” parameter contains the vulnerability (Vulnerable encoding) 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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + + + + + + + + + + + + + + + + + + + + + + + + +
Number of strainsMaximum number of DD tables
510
412
316
225
150
+ + + + + + + + + + + + + + + + + + +
SolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
+`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. +`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; +don’t use it. +The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +It is important to understand the parallelism and the concept of a chunk. +If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused +within a chunk. +No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: +* The same board is played at two tables of a team match. +* A board is played at 10 tables in a pairs tournament. +* The trump suit is the same, and there are very minor differences in the rest. +The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. +Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParDealerPar
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults *tablep 
struct parResultsDealer *sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster * prespstruct parResultsMaster * presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster *presstruct parResultsMaster *pres
char *respstruct parTextResults *resp
+The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. + +Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. + +The `vulnerable` parameter is given using Vulnerable encoding. + +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. + +The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. + +The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). + +In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. + +There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. + +Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: + +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,N 23H”: Only North makes 3 hearts. +* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. + +DealerPar() and SidesPar() give each par contract as a separate text string: + +* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. +* “3N-EW” means that E and W can both make exactly 3NT. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* SidesPar() give the par contract text strings as described above for each side. + +DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. + +After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. +Output example from ConvertToDealerTextFormat: + +“Par 110: NS 2S NS 2H” + +Output examples from ConvertToSidesTextFormat: + +“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. +”NS Par -120: W 2NT +EW Par 120: W 1NT+1” when it matters who starts the bidding. + + + + + + + + + + + + + + + + + + + + + +
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
+ +AnalysePlayPBN is just like AnalysePlayBin, except for the input format. + +The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. + +As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: + +9 10 10 10 10 9 9 + +The number of tricks are always seen from declarer’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. + + + + + + + + + + + + + + + + + + + + + +
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards *bopstruct boardsPBN *bopPBN
struct playTracesBin *plpstruct playTracesPBN *plpPBN
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
+AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. + +The AnalyseAllPlays* 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. + +Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. + + + + + + + + + + + + +
SetMaxThreadsFreeMemory
int userThreadsvoid
+SetMaxThreads returns the actual number of threads. + +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 threads 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. + +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. + +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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. + +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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. + +=== Return codes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a +different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. +Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +ConvertToDealerTextFormat, ConvertToSidesTextFormat
From 910a82b668bc8fd039aaa8005dda7160ef43cdde Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 04:48:51 +0100 Subject: [PATCH 082/199] All text typed. --- doc/dll-description.md | 471 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 466 insertions(+), 5 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index a890c51c..c4887f0c 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -167,7 +167,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int chunkSize -tr>  +  SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. @@ -845,8 +845,469 @@ If the target cannot be achieved, only one card is returned with the score set a “Reuse” means “reuse the transposition table from the previous run with the same thread number”. For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. -1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` -2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` +1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` + +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` + +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + + + + + + + + + + + + + + + +
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults * tablepstruct ddTableResults * tablep
+CalcDDtablePBN is just like CalcDDtable, except for the input format. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. + + + + + + + + + + + + + + + + + + + + + + + + +
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *resp
struct allParResults *prespstruct allParResults *presp
+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. +The “mode” parameter contains the vulnerability (Vulnerable encoding) 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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + + + + + + + + + + + + + + + + + + + + + + + + +
Number of strainsMaximum number of DD tables
510
412
316
225
150
+ + + + + + + + + + + + + + + + + + +
SolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
+`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. +`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; +don’t use it. +The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +It is important to understand the parallelism and the concept of a chunk. +If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused +within a chunk. +No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: +* The same board is played at two tables of a team match. +* A board is played at 10 tables in a pairs tournament. +* The trump suit is the same, and there are very minor differences in the rest. +The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. +Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParDealerPar
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults *tablep 
struct parResultsDealer *sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster * prespstruct parResultsMaster * presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster *presstruct parResultsMaster *pres
char *respstruct parTextResults *resp
+The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. + +Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. + +The `vulnerable` parameter is given using Vulnerable encoding. + +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. + +The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. + +The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). + +In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. + +There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. + +Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: + +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,N 23H”: Only North makes 3 hearts. +* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. + +DealerPar() and SidesPar() give each par contract as a separate text string: + +* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. +* “3N-EW” means that E and W can both make exactly 3NT. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* SidesPar() give the par contract text strings as described above for each side. + +DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. + +After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. +Output example from ConvertToDealerTextFormat: + +“Par 110: NS 2S NS 2H” + +Output examples from ConvertToSidesTextFormat: + +“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. +”NS Par -120: W 2NT +EW Par 120: W 1NT+1” when it matters who starts the bidding. + + + + + + + + + + + + + + + + + + + + + +
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
+ +AnalysePlayPBN is just like AnalysePlayBin, except for the input format. + +The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. + +As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: + +9 10 10 10 10 9 9 + +The number of tricks are always seen from declarer’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. + + + + + + + + + + + + + + + + + + + + + +
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards *bopstruct boardsPBN *bopPBN
struct playTracesBin *plpstruct playTracesPBN *plpPBN
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
+AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. + +The AnalyseAllPlays* 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. + +Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. + + + + + + + + + + + + +
SetMaxThreadsFreeMemory
int userThreadsvoid
+SetMaxThreads returns the actual number of threads. + +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 threads 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. + +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. + +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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. + +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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. + +=== Return codes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a +different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. +Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +ConvertToDealerTextFormat, ConvertToSidesTextFormat
From cef9cd2f913806498611e86b05cf2b44460a5122 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 05:55:42 +0100 Subject: [PATCH 083/199] All changes made from diff. Document is now on par with v 2.8.0 --- dds.md | 153 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 94 insertions(+), 59 deletions(-) diff --git a/dds.md b/dds.md index c4887f0c..97a95458 100644 --- a/dds.md +++ b/dds.md @@ -1,31 +1,32 @@ -Bo Haglund, Bob Richardson +Bo Haglund, Soren Hein, Bob Richardson -Rev V, 2014-10-14 +Rev X, 2014-11-16 Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ -# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 ## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. + Return codes are given at the end. Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! ## The Basic Functions -The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. +The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. -The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. +The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. -The call `FreeMemory` causes DDS to give up its dynamically allocated memory. +Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. ### The PAR Calculation Functions @@ -142,7 +143,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format. +SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! struct solvedBoards *solvedp @@ -189,7 +190,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +of the dealer. struct parResultsDealer *presp @@ -327,12 +329,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) + +  + +FreeMemoryvoid Frees DDS allocated dynamical memory.   -FreeMemoryvoidPBNFrees DDS allocated dynamical memory. +ErrorMessageint code Turns a return code into an error message string. + + ### Data sructure @@ -413,7 +421,7 @@ Common encodings are as follows int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. +unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. @@ -454,10 +462,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTables;Number of DD table deals in structure +ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableDeal deals[MAXNOOFBOARDS/4]; +struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINS @@ -535,7 +543,7 @@ Common encodings are as follows int rank[13];Rank of the returned card. Value range 2-14. -int equals[13];Lower-ranked equals. Holding PBN encoding. +int equals[13];Lower-ranked equals. Holding encoding. int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks. @@ -558,7 +566,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. @@ -571,17 +579,17 @@ Common encodings are as follows structFieldComment -ddTablesResint noOfBoards; +ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableResults results[MAXNOOFBOARDS/4]; +struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINS -structFieldComment +StructFieldComment parResultschar parScore[2][16];First index is NS/EW. Side encoding. @@ -594,17 +602,17 @@ Common encodings are as follows -structFieldComment +StructFieldComment -allParResultsstruct parResults[MAXNOOFBOARDS/20]; +allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table -structFieldComment +StructFieldComment parResultsDealerint number; @@ -620,7 +628,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parResultsMasterint score; @@ -636,7 +644,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment contractTypeint underTricks; @@ -658,7 +666,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parTextResultschar parText[2][128]; @@ -671,7 +679,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -687,7 +695,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -700,7 +708,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesBinint noOfBoards; @@ -713,7 +721,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesPBNint noOfBoards; @@ -726,26 +734,26 @@ Common encodings are as follows -structFieldComment +StructFieldComment solvedPlayint number; -int tricks[53]; +int tricks[53];Starting position and up to 52 cards -structFieldComment +StructFieldComment solvedPlaysint noOfBoards; -struct solvedPlay solved[MAXNOOFBOARDS / 10]; +struct solvedPlay solved[MAXNOOFBOARDS]; @@ -778,10 +786,12 @@ Common encodings are as follows -SolveBoardPBN is just like SolveBoard, except for the input format. +SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. + SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. @@ -842,8 +852,11 @@ If the target cannot be achieved, only one card is returned with the score set a +Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, +and we may use it for something else in the future. If you think you need it, let us know! + “Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. 1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` @@ -896,10 +909,14 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy 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. -The “mode” parameter contains the vulnerability (Vulnerable encoding) for use in the par calculation. It is set to -1 if no par calculation is to be performed. + +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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + +The maximum number of DD tables in a CallAllTables call depends on the number of strains required, see the following table: @@ -909,19 +926,19 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + - + - +
510532
412440
316353
225280
1501160
@@ -929,15 +946,15 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + @@ -945,19 +962,20 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
SolverAllChunksBinSolveAllChunksPBNSolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bopstruct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. -`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; -don’t use it. + +`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. + The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. + It is important to understand the parallelism and the concept of a chunk. + If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused -within a chunk. -No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: -* The same board is played at two tables of a team match. -* A board is played at 10 tables in a pairs tournament. -* The trump suit is the same, and there are very minor differences in the rest. -The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. -Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. + +No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. + +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! @@ -1065,7 +1083,7 @@ Output example from ConvertToDealerTextFormat: Output examples from ConvertToSidesTextFormat: “NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT +”NS Par -120: W 2NT
EW Par 120: W 1NT+1” when it matters who starts the bidding.
@@ -1150,7 +1168,11 @@ DDS then checks whether a number of threads equal to the number of cores will fi 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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. +It may be possible, 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. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. + +It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. === Return codes
@@ -1204,6 +1226,17 @@ different number of boards in its first two arguments. + + + + + + + + + + + @@ -1309,5 +1342,7 @@ AnalyseAllPlaysPBN + +
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From ac9c18711794910302322a0a45efaa7f8ee300bc Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 05:55:42 +0100 Subject: [PATCH 084/199] All changes made from diff. Document is now on par with v 2.8.0 --- doc/dll-description.md | 153 +++++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 59 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index c4887f0c..97a95458 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -1,31 +1,32 @@ -Bo Haglund, Bob Richardson +Bo Haglund, Soren Hein, Bob Richardson -Rev V, 2014-10-14 +Rev X, 2014-11-16 Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ -# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 ## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. + Return codes are given at the end. Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! ## The Basic Functions -The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. +The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. -The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. +The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. -The call `FreeMemory` causes DDS to give up its dynamically allocated memory. +Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. ### The PAR Calculation Functions @@ -142,7 +143,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format. +SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! struct solvedBoards *solvedp @@ -189,7 +190,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +of the dealer. struct parResultsDealer *presp @@ -327,12 +329,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) + +  + +FreeMemoryvoid Frees DDS allocated dynamical memory.   -FreeMemoryvoidPBNFrees DDS allocated dynamical memory. +ErrorMessageint code Turns a return code into an error message string. + + ### Data sructure @@ -413,7 +421,7 @@ Common encodings are as follows int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. +unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. @@ -454,10 +462,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTables;Number of DD table deals in structure +ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableDeal deals[MAXNOOFBOARDS/4]; +struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINS @@ -535,7 +543,7 @@ Common encodings are as follows int rank[13];Rank of the returned card. Value range 2-14. -int equals[13];Lower-ranked equals. Holding PBN encoding. +int equals[13];Lower-ranked equals. Holding encoding. int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks. @@ -558,7 +566,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. @@ -571,17 +579,17 @@ Common encodings are as follows structFieldComment -ddTablesResint noOfBoards; +ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableResults results[MAXNOOFBOARDS/4]; +struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINS -structFieldComment +StructFieldComment parResultschar parScore[2][16];First index is NS/EW. Side encoding. @@ -594,17 +602,17 @@ Common encodings are as follows -structFieldComment +StructFieldComment -allParResultsstruct parResults[MAXNOOFBOARDS/20]; +allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table -structFieldComment +StructFieldComment parResultsDealerint number; @@ -620,7 +628,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parResultsMasterint score; @@ -636,7 +644,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment contractTypeint underTricks; @@ -658,7 +666,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parTextResultschar parText[2][128]; @@ -671,7 +679,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -687,7 +695,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -700,7 +708,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesBinint noOfBoards; @@ -713,7 +721,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesPBNint noOfBoards; @@ -726,26 +734,26 @@ Common encodings are as follows -structFieldComment +StructFieldComment solvedPlayint number; -int tricks[53]; +int tricks[53];Starting position and up to 52 cards -structFieldComment +StructFieldComment solvedPlaysint noOfBoards; -struct solvedPlay solved[MAXNOOFBOARDS / 10]; +struct solvedPlay solved[MAXNOOFBOARDS]; @@ -778,10 +786,12 @@ Common encodings are as follows -SolveBoardPBN is just like SolveBoard, except for the input format. +SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. + SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. @@ -842,8 +852,11 @@ If the target cannot be achieved, only one card is returned with the score set a +Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, +and we may use it for something else in the future. If you think you need it, let us know! + “Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. 1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` @@ -896,10 +909,14 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy 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. -The “mode” parameter contains the vulnerability (Vulnerable encoding) for use in the par calculation. It is set to -1 if no par calculation is to be performed. + +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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + +The maximum number of DD tables in a CallAllTables call depends on the number of strains required, see the following table: @@ -909,19 +926,19 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + - + - +
510532
412440
316353
225280
1501160
@@ -929,15 +946,15 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + @@ -945,19 +962,20 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
SolverAllChunksBinSolveAllChunksPBNSolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bopstruct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. -`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; -don’t use it. + +`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. + The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. + It is important to understand the parallelism and the concept of a chunk. + If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused -within a chunk. -No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: -* The same board is played at two tables of a team match. -* A board is played at 10 tables in a pairs tournament. -* The trump suit is the same, and there are very minor differences in the rest. -The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. -Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. + +No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. + +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! @@ -1065,7 +1083,7 @@ Output example from ConvertToDealerTextFormat: Output examples from ConvertToSidesTextFormat: “NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT +”NS Par -120: W 2NT
EW Par 120: W 1NT+1” when it matters who starts the bidding.
@@ -1150,7 +1168,11 @@ DDS then checks whether a number of threads equal to the number of cores will fi 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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. +It may be possible, 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. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. + +It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. === Return codes
@@ -1204,6 +1226,17 @@ different number of boards in its first two arguments. + + + + + + + + + + + @@ -1309,5 +1342,7 @@ AnalyseAllPlaysPBN + +
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From f5ce5f7674164086b1b6fe6fe3fd2fb02c81e22d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 07:56:46 +0100 Subject: [PATCH 085/199] Changes made focussing on Markup syntax --- dds.md | 172 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 91 insertions(+), 81 deletions(-) diff --git a/dds.md b/dds.md index 97a95458..32bef118 100644 --- a/dds.md +++ b/dds.md @@ -18,7 +18,7 @@ The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand a ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. +The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. @@ -51,7 +51,6 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - @@ -72,7 +71,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -90,7 +89,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -100,18 +99,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -120,14 +119,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -136,65 +135,65 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - - + @@ -204,10 +203,10 @@ of the dealer. - + - + @@ -217,24 +216,24 @@ of the dealer. - + - + - + - + - + @@ -244,10 +243,10 @@ of the dealer. - + - + @@ -257,23 +256,23 @@ of the dealer. - + - + - + - + @@ -283,7 +282,7 @@ of the dealer. - + @@ -296,33 +295,33 @@ of the dealer. - + - + - + - + - + - + - + @@ -343,8 +342,10 @@ of the dealer.
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndex
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndexCalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded.SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *prespstruct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int dealer
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster * prespstruct parResultsMaster \* presp
int dealer
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char *respchar \*resp
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char *respchar \*resp
 
int vulnerable
struct ddTableResults *tablepstruct ddTableResults \*tablep
struct parResults *prespstruct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablepstruct ddTableResults \*tablep
int vulnerable
struct parResults *prespstruct parResults \*presp
 
struct playTraceBin play
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId struct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plpstruct playTracesBin \*plp
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBNstruct playTracesPBN \*plpPBN
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
-### Data sructure + +## Data structure Common encodings are as follows + @@ -465,7 +466,7 @@ Common encodings are as follows - + @@ -582,7 +583,7 @@ Common encodings are as follows - + @@ -758,7 +759,8 @@ Common encodings are as follows
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
-### Functions +## Functions + @@ -779,16 +781,17 @@ Common encodings are as follows - +
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
+ SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. -SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. @@ -852,6 +855,7 @@ If the target cannot be achieved, only one card is returned with the score set a + Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, and we may use it for something else in the future. If you think you need it, let us know! @@ -877,12 +881,13 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN -struct ddTableResults * tablepstruct ddTableResults * tablep +struct ddTableResults \* tablepstruct ddTableResults \* tablep + CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. @@ -892,7 +897,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + @@ -901,16 +906,17 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + - +
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealspstruct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint modeint trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *respstruct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults *prespstruct allParResults *prespstruct allParResults \*prespstruct allParResults \*presp
+ 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. +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. 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. @@ -951,21 +957,22 @@ The maximum number of DD tables in a CallAllTables call depends on the number of -struct boards *bopstruct boards *bopstruct boardsPBN *bop +struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop -struct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp +struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp int chunkSizeint chunkSize + `SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. `SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. -The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. It is important to understand the parallelism and the concept of a chunk. @@ -985,10 +992,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResults *prespstruct parResultsDealer *presp +struct parResults \*prespstruct parResultsDealer \*presp int vulnerableint dealer @@ -1003,10 +1010,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or Sidespar  -struct ddTableResults *tablep  +struct ddTableResults \*tablep  -struct parResultsDealer *sidesRes[2]  +struct parResultsDealer \*sidesRes[2]  int vulnerable  @@ -1018,10 +1025,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or DealerParBinSidesParBin -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResultsMaster * prespstruct parResultsMaster * presp +struct parResultsMaster \* prespstruct parResultsMaster \* presp int vulnerableint dealer @@ -1036,13 +1043,14 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or ConvertToDealerTextForamatConvertToSidesTextFormat -struct parResultsMaster *presstruct parResultsMaster *pres +struct parResultsMaster \*presstruct parResultsMaster \*pres -char *respstruct parTextResults *resp +char \*respstruct parTextResults \*resp + The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. @@ -1061,8 +1069,7 @@ There may be several par contracts, for instance 3NT just making and 5C just mak Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. * “NS:NS 23S,N 23H”: Only North makes 3 hearts. * “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. @@ -1070,7 +1077,7 @@ DealerPar() and SidesPar() give each par contract as a separate text string: * “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. * “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. * SidesPar() give the par contract text strings as described above for each side. DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. @@ -1100,7 +1107,7 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding. struct playTraceBin playstruct playTracePBN playPBN -struct solvedPlay *solvedpstruct solvedPlay *solvedp +struct solvedPlay \*solvedpstruct solvedPlay \*solvedp int thrIdint thrId @@ -1126,22 +1133,23 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one -struct boards *bopstruct boardsPBN *bopPBN +struct boards \*bopstruct boardsPBN \*bopPBN -struct playTracesBin *plpstruct playTracesPBN *plpPBN +struct playTracesBin \*plpstruct playTracesPBN \*plpPBN -struct solvedPlays *solvedpstruct solvedPlays *solvedp +struct solvedPlays \*solvedpstruct solvedPlays \*solvedp int chunkSizeint chunkSize + AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. -The AnalyseAllPlays* 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. +The AnalyseAllPlays\* 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. Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. @@ -1157,6 +1165,7 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi + SetMaxThreads returns the actual number of threads. 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 threads than there are processor cores, as this will only require more memory and will not improve performance. Within these constraints, DDS auto-configures the @@ -1174,7 +1183,8 @@ SetMaxThreads can be called multiple times even within the same session. So it i It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. -=== Return codes +## Return codes + @@ -1237,7 +1247,7 @@ different number of boards in its first two arguments. - @@ -1252,13 +1262,13 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + - + - +
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
From 109fa591e97f1eb33d669a9349922f4559a962e4 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 07:56:46 +0100 Subject: [PATCH 086/199] Changes made focussing on Markup syntax --- doc/dll-description.md | 172 ++++++++++++++++++++++------------------- 1 file changed, 91 insertions(+), 81 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 97a95458..32bef118 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -18,7 +18,7 @@ The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand a ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. +The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. @@ -51,7 +51,6 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - @@ -72,7 +71,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -90,7 +89,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -100,18 +99,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -120,14 +119,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -136,65 +135,65 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - - + @@ -204,10 +203,10 @@ of the dealer. - + - + @@ -217,24 +216,24 @@ of the dealer. - + - + - + - + - + @@ -244,10 +243,10 @@ of the dealer. - + - + @@ -257,23 +256,23 @@ of the dealer. - + - + - + - + @@ -283,7 +282,7 @@ of the dealer. - + @@ -296,33 +295,33 @@ of the dealer. - + - + - + - + - + - + - + @@ -343,8 +342,10 @@ of the dealer.
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndex
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndexCalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded.SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *prespstruct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int dealer
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster * prespstruct parResultsMaster \* presp
int dealer
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char *respchar \*resp
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char *respchar \*resp
 
int vulnerable
struct ddTableResults *tablepstruct ddTableResults \*tablep
struct parResults *prespstruct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablepstruct ddTableResults \*tablep
int vulnerable
struct parResults *prespstruct parResults \*presp
 
struct playTraceBin play
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId struct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plpstruct playTracesBin \*plp
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBNstruct playTracesPBN \*plpPBN
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
-### Data sructure + +## Data structure Common encodings are as follows + @@ -465,7 +466,7 @@ Common encodings are as follows - + @@ -582,7 +583,7 @@ Common encodings are as follows - + @@ -758,7 +759,8 @@ Common encodings are as follows
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
-### Functions +## Functions + @@ -779,16 +781,17 @@ Common encodings are as follows - +
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
+ SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. -SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. @@ -852,6 +855,7 @@ If the target cannot be achieved, only one card is returned with the score set a + Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, and we may use it for something else in the future. If you think you need it, let us know! @@ -877,12 +881,13 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN -struct ddTableResults * tablepstruct ddTableResults * tablep +struct ddTableResults \* tablepstruct ddTableResults \* tablep + CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. @@ -892,7 +897,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + @@ -901,16 +906,17 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + - +
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealspstruct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint modeint trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *respstruct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults *prespstruct allParResults *prespstruct allParResults \*prespstruct allParResults \*presp
+ 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. +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. 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. @@ -951,21 +957,22 @@ The maximum number of DD tables in a CallAllTables call depends on the number of -struct boards *bopstruct boards *bopstruct boardsPBN *bop +struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop -struct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp +struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp int chunkSizeint chunkSize + `SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. `SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. -The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. It is important to understand the parallelism and the concept of a chunk. @@ -985,10 +992,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResults *prespstruct parResultsDealer *presp +struct parResults \*prespstruct parResultsDealer \*presp int vulnerableint dealer @@ -1003,10 +1010,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or Sidespar  -struct ddTableResults *tablep  +struct ddTableResults \*tablep  -struct parResultsDealer *sidesRes[2]  +struct parResultsDealer \*sidesRes[2]  int vulnerable  @@ -1018,10 +1025,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or DealerParBinSidesParBin -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResultsMaster * prespstruct parResultsMaster * presp +struct parResultsMaster \* prespstruct parResultsMaster \* presp int vulnerableint dealer @@ -1036,13 +1043,14 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or ConvertToDealerTextForamatConvertToSidesTextFormat -struct parResultsMaster *presstruct parResultsMaster *pres +struct parResultsMaster \*presstruct parResultsMaster \*pres -char *respstruct parTextResults *resp +char \*respstruct parTextResults \*resp + The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. @@ -1061,8 +1069,7 @@ There may be several par contracts, for instance 3NT just making and 5C just mak Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. * “NS:NS 23S,N 23H”: Only North makes 3 hearts. * “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. @@ -1070,7 +1077,7 @@ DealerPar() and SidesPar() give each par contract as a separate text string: * “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. * “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. * SidesPar() give the par contract text strings as described above for each side. DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. @@ -1100,7 +1107,7 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding. struct playTraceBin playstruct playTracePBN playPBN -struct solvedPlay *solvedpstruct solvedPlay *solvedp +struct solvedPlay \*solvedpstruct solvedPlay \*solvedp int thrIdint thrId @@ -1126,22 +1133,23 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one -struct boards *bopstruct boardsPBN *bopPBN +struct boards \*bopstruct boardsPBN \*bopPBN -struct playTracesBin *plpstruct playTracesPBN *plpPBN +struct playTracesBin \*plpstruct playTracesPBN \*plpPBN -struct solvedPlays *solvedpstruct solvedPlays *solvedp +struct solvedPlays \*solvedpstruct solvedPlays \*solvedp int chunkSizeint chunkSize + AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. -The AnalyseAllPlays* 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. +The AnalyseAllPlays\* 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. Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. @@ -1157,6 +1165,7 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi + SetMaxThreads returns the actual number of threads. 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 threads than there are processor cores, as this will only require more memory and will not improve performance. Within these constraints, DDS auto-configures the @@ -1174,7 +1183,8 @@ SetMaxThreads can be called multiple times even within the same session. So it i It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. -=== Return codes +## Return codes + @@ -1237,7 +1247,7 @@ different number of boards in its first two arguments. - @@ -1252,13 +1262,13 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + - + - +
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
From a0133b31cd9149acacd8eac858fad0429380ae91 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 21:21:16 +0100 Subject: [PATCH 087/199] Extra commit before copying the file --- dds.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 32bef118..452d2ca3 100644 --- a/dds.md +++ b/dds.md @@ -22,7 +22,7 @@ The double dummy trick values for all 5 \* 4 = 20 possible combinations of a han To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. From ee75d5785eaa493037087f62238681de45afbf08 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 21:21:16 +0100 Subject: [PATCH 088/199] Extra commit before copying the file --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 32bef118..452d2ca3 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -22,7 +22,7 @@ The double dummy trick values for all 5 \* 4 = 20 possible combinations of a han To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. From 3c5517deb2b3ec3567bbc301b4d3976776496742 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 22:14:02 +0100 Subject: [PATCH 089/199] Re-removed dds.md --- dds.md | 1358 -------------------------------------------------------- 1 file changed, 1358 deletions(-) delete mode 100644 dds.md diff --git a/dds.md b/dds.md deleted file mode 100644 index 452d2ca3..00000000 --- a/dds.md +++ /dev/null @@ -1,1358 +0,0 @@ -Bo Haglund, Soren Hein, Bob Richardson - -Rev X, 2014-11-16 - -Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ - -# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 -## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. - -Return codes are given at the end. - -Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! - -## The Basic Functions - -The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. - -### The Multi-Thread Double Dummy Solver Functions - -The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. - -To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. - -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. - -The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. - -Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. - -### The PAR Calculation Functions - -The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. - -Two alternatives are given: - -1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. -2. The dealer hand is assumed to “start the bidding”. - -The presentation of the par score and contracts are given in alternative formats. - -The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. - -The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. - -It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. - -The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. - -### Double Dummy Value Analyser Functions - -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionArgumentsFormatComment
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge -of the dealer.
struct parResultsDealer \*presp
int dealer
int vulnerable
 
DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster \* presp
int dealer
int vulnerable
 
ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char \*resp
 
SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
int vulnerable
 
ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char \*resp
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTableResults \*tablep
struct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults \*tablep
int vulnerable
struct parResults \*presp
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
struct solvedPlay \*solvedp
int thrId
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
struct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin \*plp
struct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN \*plpPBN
struct solvedPlays \*solvedp
int chunkSize
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
ErrorMessageint code Turns a return code into an error message string.
-
- -## Data structure -Common encodings are as follows - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
StructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
StructFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
StructFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
StructFieldComment
parTextResultschar parText[2][128];
int equal;
StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
StructFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
StructFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
StructFieldComment
solvedPlayint number;
int tricks[53];Starting position and up to 52 cards
StructFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- -## Functions - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
- -SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. - -SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. - -If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. - -SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. - -There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. - -The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. - -For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
targetsolutionscomment
-11Find the maximum number of tricks for the side to -play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to -play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with -score set to 0.
02Return all cards that legal to play, with score set to -0.
1 .. 131If score is -1: Target cannot be reached.
-If score is 0: In fact no tricks at all can be won.
-If score is > 0: score will always equal target, even if more tricks can be won.
-One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
-If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
- -Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, -and we may use it for something else in the future. If you think you need it, let us know! - -“Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. - -1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` - -2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` - -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` - -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` - - - - - - - - - - - - - - - -
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablep
- -CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. - - - - - - - - - - - - - - - - - - - - - - - - -
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults \*prespstruct allParResults \*presp
- -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. - -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: - - - - - - - - - - - - - - - - - - - - - - - - -
Number of strainsMaximum number of DD tables
532
440
353
280
1160
- - - - - - - - - - - - - - - - - - -
SolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp
int chunkSizeint chunkSize
- -`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. - -`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. - -The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. - -It is important to understand the parallelism and the concept of a chunk. - -If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. - -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. - -No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. - -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! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResults \*prespstruct parResultsDealer \*presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults \*tablep 
struct parResultsDealer \*sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResultsMaster \* prespstruct parResultsMaster \* presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
char \*respstruct parTextResults \*resp
- -The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. - -Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. - -The `vulnerable` parameter is given using Vulnerable encoding. - -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. - -The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. - -The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). - -In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. - -There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. - -Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: - -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. -* “NS:NS 23S,N 23H”: Only North makes 3 hearts. -* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. - -DealerPar() and SidesPar() give each par contract as a separate text string: - -* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. -* “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. -* SidesPar() give the par contract text strings as described above for each side. - -DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. - -After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. -Output example from ConvertToDealerTextFormat: - -“Par 110: NS 2S NS 2H” - -Output examples from ConvertToSidesTextFormat: - -“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT
-EW Par 120: W 1NT+1” when it matters who starts the bidding. - - - - - - - - - - - - - - - - - - - - - -
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedp
int thrIdint thrId
- -AnalysePlayPBN is just like AnalysePlayBin, except for the input format. - -The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. - -As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: - -9 10 10 10 10 9 9 - -The number of tricks are always seen from declarer’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. - - - - - - - - - - - - - - - - - - - - - -
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedp
int chunkSizeint chunkSize
- -AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. - -The AnalyseAllPlays\* 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. - -Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. - - - - - - - - - - - - -
SetMaxThreadsFreeMemory
int userThreadsvoid
- -SetMaxThreads returns the actual number of threads. - -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 threads 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. - -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. - -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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. - -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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. - -It may be possible, 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. - -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. - -It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. - -## Return codes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a -different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) -Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. -Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, -AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, -ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From 8e1cfa41f623bdec43941bafa737be09457a41b0 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 23:16:59 +0100 Subject: [PATCH 090/199] Added anchors --- doc/dll-description.md | 113 +++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 452d2ca3..75df8cbc 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play int target @@ -77,7 +77,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. +SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. int target @@ -96,21 +96,21 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) +CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) struct ddTableResults \* tablep   -CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. +CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. struct ddTableResults \* tablep   -CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded. +CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded. int mode @@ -126,7 +126,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format. +CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format. int mode @@ -142,14 +142,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”! +SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”! struct solvedBoards \*solvedp   -SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded. struct solvedBoards \*solvedp @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use! struct solvedBoards \*solvedp @@ -169,7 +169,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded. struct solvedBoards \*solvedp @@ -179,7 +179,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table. +Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table. struct parResults \*presp @@ -189,7 +189,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer. @@ -203,7 +203,7 @@ of the dealer.   -DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output. +DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output. struct parResultsMaster \* presp @@ -216,14 +216,14 @@ of the dealer.   -ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin. +ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin. char \*resp   -SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format. +SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format. struct parResultsDealer \*presp @@ -233,7 +233,7 @@ of the dealer.   -SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output. +SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output. struct parResultsMaster sidesRes[2] @@ -243,14 +243,14 @@ of the dealer.   -ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin. +ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin. char \*resp   -CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! int vulnerable @@ -263,7 +263,7 @@ of the dealer.   -CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! struct ddTableResults \*tablep @@ -276,7 +276,7 @@ of the dealer.   -AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. struct playTraceBin play @@ -289,7 +289,7 @@ of the dealer.   -AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. struct playTracePBN playPBN @@ -302,7 +302,7 @@ of the dealer.   -AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. +AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. struct playTracesBin \*plp @@ -315,7 +315,7 @@ of the dealer.   -AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. +AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. struct playTracesPBN \*plpPBN @@ -328,15 +328,15 @@ of the dealer.   -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)   -FreeMemoryvoid Frees DDS allocated dynamical memory. +FreeMemoryvoid Frees DDS allocated dynamical memory.   -ErrorMessageint code Turns a return code into an error message string. +ErrorMessageint code Turns a return code into an error message string. @@ -354,7 +354,7 @@ Common encodings are as follows -SuitSpades0 +SuitSpades0 Hearts1 @@ -368,7 +368,7 @@ Common encodings are as follows NT4   -HandNorth0 +HandNorth0 East1 @@ -379,12 +379,12 @@ Common encodings are as follows West3   -SideN-S0 +SideN-S0 E-W1   -CardBit 2Rank of deuce +CardBit 2Rank of deuce ...  @@ -395,13 +395,14 @@ Common encodings are as follows Bit 14Rank of ace   -HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero. +HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.   -PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K +PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K + @@ -410,7 +411,7 @@ Common encodings are as follows - + @@ -431,7 +432,7 @@ Common encodings are as follows - + @@ -453,7 +454,7 @@ Common encodings are as follows - + @@ -463,7 +464,7 @@ Common encodings are as follows - + @@ -476,7 +477,7 @@ Common encodings are as follows - + @@ -489,7 +490,7 @@ Common encodings are as follows - + @@ -511,7 +512,7 @@ Common encodings are as follows - + @@ -532,7 +533,7 @@ Common encodings are as follows - + @@ -557,7 +558,7 @@ Common encodings are as follows - + @@ -570,7 +571,7 @@ Common encodings are as follows - + @@ -580,7 +581,7 @@ Common encodings are as follows - + @@ -593,7 +594,7 @@ Common encodings are as follows - + @@ -606,7 +607,7 @@ Common encodings are as follows - + @@ -616,7 +617,7 @@ Common encodings are as follows - + @@ -632,7 +633,7 @@ Common encodings are as follows - + @@ -648,7 +649,7 @@ Common encodings are as follows - + @@ -670,7 +671,7 @@ Common encodings are as follows - + @@ -683,7 +684,7 @@ Common encodings are as follows - + @@ -699,7 +700,7 @@ Common encodings are as follows - + @@ -712,7 +713,7 @@ Common encodings are as follows - + @@ -725,7 +726,7 @@ Common encodings are as follows - + @@ -738,7 +739,7 @@ Common encodings are as follows - + @@ -751,7 +752,7 @@ Common encodings are as follows - + @@ -764,7 +765,7 @@ Common encodings are as follows
dealint trump;Suit encodingdealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.structFieldComment
dealPBNint trump;Suit encodingdealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. HoldingddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLESddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINSstructFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structureddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];structFieldComment
boardsint noOfBoards;Number of boardsboardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];structFieldComment
boardsPBNint noOfBoards;Number of boardsboardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.structFieldComment
solvedBoardsint noOfBoards;solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLESddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINSStructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD tableallParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;parResultsDealerint number;
int score;StructFieldComment
parResultsMasterint score;parResultsMasterint score;
int number;StructFieldComment
contractTypeint underTricks;contractTypeint underTricks;
int overTricks;StructFieldComment
parTextResultschar parText[2][128];parTextResultschar parText[2][128];
int equal;StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.StructFieldComment
playTracesBinint noOfBoards;playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];StructFieldComment
playTracesPBNint noOfBoards;playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];StructFieldComment
solvedPlayint number;solvedPlayint number;
int tricks[53];Starting position and up to 52 cardsStructFieldComment
solvedPlaysint noOfBoards;solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- + From 495109e6328faf16f47369824acf3a63dd2114db Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 01:03:04 +0100 Subject: [PATCH 091/199] Moved the anchors to the explanatory section --- doc/dll-description.md | 106 ++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 39 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 75df8cbc..d886dbce 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -8,7 +8,7 @@ Latest DLL issue with this description is available at http://www.bahnhof.se/wb7 ## Callable functions The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. -Return codes are given at the end. +[Return codes](#ReturnCodes) are given at the end. Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -77,7 +77,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -96,21 +96,21 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -126,7 +126,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -142,14 +142,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -169,7 +169,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -179,7 +179,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -189,7 +189,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - @@ -203,7 +203,7 @@ of the dealer. - + @@ -216,14 +216,14 @@ of the dealer. - + - + @@ -233,7 +233,7 @@ of the dealer. - + @@ -243,14 +243,14 @@ of the dealer. - + - + @@ -263,7 +263,7 @@ of the dealer. - + @@ -276,7 +276,7 @@ of the dealer. - + @@ -289,7 +289,7 @@ of the dealer. - + @@ -302,7 +302,7 @@ of the dealer. - + @@ -315,7 +315,7 @@ of the dealer. - + @@ -328,15 +328,15 @@ of the dealer. - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1312,75 +1312,75 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - - +
SolveBoardSolveoardPBNSolveBoardSolveBoardPBN
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play[SolveBoard](#SolveBoard)struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.[SolveBoardPBN](#SolveBoardPBN)struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)[CalcDDtable](#CalcDDtable)struct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.[CalcDDtablePBN](#CalcDDtablePBN)struct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.[CalcAllTables](#CalcAllTables)struct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
 
CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.[CalcAllTablesPBN](#CalcAllTablesPBN)struct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
 
SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”![SolveAllBoards](#SolveAllBoards)struct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.[SolveAllChunksBin](#SolveAllChunksBin)struct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
 
SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use![SolveAllChunks](#SolveAllChunks)struct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards \*solvedp
 
SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.[SolveAllChunksPBN](#SolveAllChunksPBN)struct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
 
Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.[Par](#Par)struct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults \*presp
 
DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge +[DealerPar](#DealerPar)struct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
 
DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.[DealerParBin](#DealerParBin)struct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster \* presp
 
ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.[ConvertToDealerTextFormat](#ConvertToDealerTextFormat)struct parResultsMaster \*presTextExample of text output from DealerParBin.
char \*resp
 
SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.[SidesPar](#SidesPar)struct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer \*presp
 
SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.[SidesParBin](#SidesParBin)struct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
 
ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.[ConvertToSidesTextFormat](#ConvertToSidesTextFormat)struct parResultsMaster \*presTextExample of text output from SidesParBin.
char \*resp
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead![CalcPar](#CalcPar)struct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead![CalcParPBN](#CalcParPBN)struct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults \*tablep
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.[AnalysePlayBin](#AnalysePlayBin)struct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.[AnalysePlayPBN](#AnalysePlayPBN)struct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
 
AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.[AnalyseAllPlaysBin](#AnalyseAllPlaysBin)struct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin \*plp
 
AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.[AnalyseAllPlaysPBN](#AnalyseAllPlaysPBN)struct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN \*plpPBN
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)[SetMaxThreads](#SetMaxThreads)int userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
FreeMemoryvoid Frees DDS allocated dynamical memory.[FreeMemory](#FreeMemory)void Frees DDS allocated dynamical memory.
 
ErrorMessageint code Turns a return code into an error message string.[ErrorMessage](#ErrorMessage)int code Turns a return code into an error message string.
@@ -765,7 +765,7 @@ Common encodings are as follows - + @@ -874,7 +874,7 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure
SolveBoardSolveBoardPBNSolveBoardSolveBoardPBN
- + @@ -893,7 +893,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy
CalcDDtableCalcDDtablePBNCalcDDtableCalcDDtablePBN
- + @@ -953,7 +953,7 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
CalcAllTablesCalcAllTablesPBNCalcAllTablesCalcAllTablesPBN
- + @@ -988,7 +988,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or
SolveAllBoardsSolverAllChunksBinSolveAllChunksPBNSolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
- + @@ -1008,7 +1008,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + @@ -1023,7 +1023,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + @@ -1041,7 +1041,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + @@ -1097,7 +1097,35 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding.
ParDealerParParDealerPar
 
Sidespar SidesPar 
struct ddTableResults \*tablep  
DealerParBinSidesParBinDealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep 
ConvertToDealerTextForamatConvertToSidesTextFormatConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
- + + + + + + + + + + + + + + + + + +
AnalysePlayBinAnalysePlayPBNCalcParCalcParPBN
struct ddTableDeal dlstruct ddTableDealPBN dlN
int vulnerablestruct ddTableResults * tp
struct ddTableResults * tpint vulnerable
struct parResults *prespstruct parResults *presp
+ +CalcParPBN is just like CalcPar, except for the input format. + +Each of these functions calculates both the double-dummy table solution and the par solution to a given deal. + +Both functions are deprecated. Instead use one of the CalcDDtable functions followed by Par(). + + + + + @@ -1129,7 +1157,7 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one
AnalysePlayBinAnalysePlayPBN
- + @@ -1157,7 +1185,7 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi
AnalyseAllPlaysBinAnalyseAllPlaysPBNAnalyseAllPlaysBinAnalyseAllPlaysPBN
- + @@ -1183,7 +1211,7 @@ It may be possible, especially on non-Windows systems, to call SetMaxThreads() a SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. - + ## Return codes
SetMaxThreadsFreeMemorySetMaxThreadsFreeMemory
From ca54819b79bf790d012d7fbf995c3dc5d83e8d59 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 01:33:24 +0100 Subject: [PATCH 092/199] Added most of the links --- doc/dll-description.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index d886dbce..faa11a60 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -343,7 +343,7 @@ of the dealer.
-## Data structure +## Data structures Common encodings are as follows @@ -1310,7 +1310,7 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + From a880fb55ba3527903a9181e17f56ab3ccee068d5 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 01:34:29 +0100 Subject: [PATCH 093/199] Added most of the links --- doc/dll-description.md | 102 ++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index faa11a60..562db9bd 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -71,13 +71,13 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + @@ -89,28 +89,28 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + @@ -119,14 +119,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -135,65 +135,65 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - - + @@ -203,10 +203,10 @@ of the dealer. - + - + @@ -216,83 +216,83 @@ of the dealer. - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -302,26 +302,26 @@ of the dealer. - + - + - + - + - + - + From ba13da748c09bb10b0d58ab45ef3bcd7c6a264aa Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 02:49:27 +0100 Subject: [PATCH 094/199] Redid links because Github doesn't do markdoen inside html tags --- doc/dll-description.md | 168 ++++++++++++++++++++--------------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 562db9bd..dc29c498 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,284 +59,284 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -336,10 +336,9 @@ of the dealer. - + -
Rev A2006-02-25First issueRev A2006-02-25First issue
Rev B2006-03-20Updated issue
[SolveBoard](#SolveBoard)struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play[SolveBoard](#SolveBoard)struct [deal](#deal) dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int targetint mode
struct futureTricks \*futpstruct [futureTricks](#futureTricks) \*futp
int threadIndex
 
[SolveBoardPBN](#SolveBoardPBN)struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.[SolveBoardPBN](#SolveBoardPBN)struct [dealPBN](#dealPBN) dlPBNPBNAs SolveBoard, but with PBN deal format.
int targetint mode
struct futureTricks \*futpstruct [futureTricks](#futureTricks) \*futp
int threadIndex
 
[CalcDDtable](#CalcDDtable)struct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)[CalcDDtable](#CalcDDtable)struct [ddTableDeal](#ddTableDeal) tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults \* tablepstruct [ddTableResults](#ddTableResults) \* tablep
 
[CalcDDtablePBN](#CalcDDtablePBN)struct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.[CalcDDtablePBN](#CalcDDtablePBN)struct [ddTableDealPBN](#ddTableDealPBN) tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults \* tablepstruct [ddTableResults](#ddTableResults) \* tablep
 
[CalcAllTables](#CalcAllTables)struct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.[CalcAllTables](#CalcAllTables)struct [ddTableDeals](#ddTableDeals) \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint trumpFilter[5]
struct ddTablesRes \*respstruct [ddTablesRes](#ddtablesRes) \*resp
struct allParResults \*presstruct [allParResults](#allParResults) \*pres
 
[CalcAllTablesPBN](#CalcAllTablesPBN)struct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.[CalcAllTablesPBN](#CalcAllTablesPBN)struct [ddTableDealsPBN](#ddTableDealsPBN) \*dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint trumpFilter[5]
struct ddTablesRes \*respstruct [ddTablesRes](#ddTablesRes) \*resp
struct allParResults \*presstruct [allParResults](#allParResults) \*pres
 
[SolveAllBoards](#SolveAllBoards)struct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”![SolveAllBoards](#SolveAllBoards)struct [boardsPBN](#boardsPBN) \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards \*solvedpstruct [solvedBoards](#solvedBoards) \*solvedp
 
[SolveAllChunksBin](#SolveAllChunksBin)struct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.[SolveAllChunksBin](#SolveAllChunksBin)struct [boards](#boards) \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedpstruct [solvedBoards](#solvedBoards) \*solvedp
int chunkSize
 
[SolveAllChunks](#SolveAllChunks)struct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use![SolveAllChunks](#SolveAllChunks)struct [boardsPBN](#boardsPBN) \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards \*solvedpstruct [solvedBoards](#solvedBoards) \*solvedp
int chunkSize
 
[SolveAllChunksPBN](#SolveAllChunksPBN)struct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.[SolveAllChunksPBN](#SolveAllChunksPBN)struct [boardsPBN](#boardsPBN) \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedpstruct [solvedBoards](#solvedBoards) \*solvedp
int chunkSize
 
[Par](#Par)struct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.[Par](#Par)struct [ddTableResults](#ddTableResults) \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults \*prespstruct [parResults](#parResults) \*presp
int vulnerable
 
[DealerPar](#DealerPar)struct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge +[DealerPar](#DealerPar)struct [ddTableResults](#ddTableResults) \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer \*prespstruct [parResultsDealer](#parResultsDealer) \*presp
int dealer
 
[DealerParBin](#DealerParBin)struct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.[DealerParBin](#DealerParBin)struct [ddTableResults](#ddTableResults) \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster \* prespstruct [parResultsMaster](#parResultsMaster) \* presp
int dealer
 
[ConvertToDealerTextFormat](#ConvertToDealerTextFormat)struct parResultsMaster \*presTextExample of text output from DealerParBin.[ConvertToDealerTextFormat](#ConvertToDealerTextFormat)struct [parResultsMaster](#parResultsMaster) \*presTextExample of text output from DealerParBin.
char \*resp
 
[SidesPar](#SidesPar)struct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.[SidesPar](#SidesPar)struct [ddTableResults](#ddTableResults) \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer \*prespstruct [parResultsDealer](#parResultsDealer) \*presp
int vulnerable
 
[SidesParBin](#SidesParBin)struct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.[SidesParBin](#SidesParBin)struct [ddTableResults](#ddTableResults) \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]struct [parResultsMaster](#parResultsMaster) sidesRes[2]
int vulnerable
 
[ConvertToSidesTextFormat](#ConvertToSidesTextFormat)struct parResultsMaster \*presTextExample of text output from SidesParBin.[ConvertToSidesTextFormat](#ConvertToSidesTextFormat)struct [parResultsMaster](#parResultsMaster) \*presTextExample of text output from SidesParBin.
char \*resp
 
[CalcPar](#CalcPar)struct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead![CalcPar](#CalcPar)struct [ddTableDeal](#ddTableDeal) tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTableResults \*tablepstruct [ddTableResults](#ddTabeleResults) \*tablep
struct parResults \*prespstruct [parResults](#parResults) \*presp
 
[CalcParPBN](#CalcParPBN)struct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead![CalcParPBN](#CalcParPBN)struct [ddTableDealPBN](#ddTableDealPBN) tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults \*tablepstruct [ddTableResult](#ddTableResults)s \*tablep
int vulnerable
struct parResults \*prespstruct [parResults](#parResults) \*presp
 
[AnalysePlayBin](#AnalysePlayBin)struct deal dlBinaryReturns the par result after each card in a particular play sequence.[AnalysePlayBin](#AnalysePlayBin)struct [deal](#deal) dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin playstruct [playTraceBin](#playTraceBin) play
struct solvedPlay \*solvedpstruct [solvedPlay](#solvedPlay) \*solvedp
int thrId
 
[AnalysePlayPBN](#AnalysePlayPBN)struct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.[AnalysePlayPBN](#AnalysePlayPBN)struct [dealPBN](#dealPBN) dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBNstruct [playTracePBN](#playTracePBN) playPBN
struct solvedPlay \*solvedp
 
[AnalyseAllPlaysBin](#AnalyseAllPlaysBin)struct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.[AnalyseAllPlaysBin](#AnalyseAllPlaysBin)struct [boards](#boards) \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin \*plpstruct [playTracesBi](#playTracesBin)n \*plp
struct solvedPlays \*solvedpstruct [solvedPlays](#solvedPlays) \*solvedp
int chunkSize
 
[AnalyseAllPlaysPBN](#AnalyseAllPlaysPBN)struct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.[AnalyseAllPlaysPBN](#AnalyseAllPlaysPBN)struct [boardsPBN](#boardsPBN) \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN \*plpPBNstruct [playTracesPBN](#playTracesPBN) \*plpPBN
struct solvedPlays \*solvedpstruct [solvedPlay](#solvedPlay)s \*solvedp
int chunkSize
[SolveBoard](#SolveBoard)struct [deal](#deal) dlBinaryThe most basic function, solves a single hand from the beginning or from later playSolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int targetint target
int solutionsint solutions
int modeint mode
struct [futureTricks](#futureTricks) \*futpstruct futureTricks *futp
int threadIndex
 
[SolveBoardPBN](#SolveBoardPBN)struct [dealPBN](#dealPBN) dlPBNPBNAs SolveBoard, but with PBN deal format.SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int targetint target
int solutionsint solutions
int modeint mode
struct [futureTricks](#futureTricks) \*futpstruct futureTricks *futp
int threadIndexint threadIndex
 
[CalcDDtable](#CalcDDtable)struct [ddTableDeal](#ddTableDeal) tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct [ddTableResults](#ddTableResults) \* tablepstruct ddTableResults * tablep
 
[CalcDDtablePBN](#CalcDDtablePBN)struct [ddTableDealPBN](#ddTableDealPBN) tableDealPBNPBNAs CalcDDtable, but with PBN deal format.CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct [ddTableResults](#ddTableResults) \* tablepstruct ddTableResults * tablep
 
[CalcAllTables](#CalcAllTables)struct [ddTableDeals](#ddTableDeals) \*dealspBinarySolves a number of hands in parallel. Multi-threaded.CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct [ddTablesRes](#ddtablesRes) \*respstruct ddtablesRes *resp
struct [allParResults](#allParResults) \*presstruct allParResultsa> *pres
 
[CalcAllTablesPBN](#CalcAllTablesPBN)struct [ddTableDealsPBN](#ddTableDealsPBN) \*dealspPBNAs CalcAllTables, but with PBN deal format.CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct [ddTablesRes](#ddTablesRes) \*respstruct ddTablesRes *resp
struct [allParResults](#allParResults) \*presstruct allParResults *pres
 
[SolveAllBoards](#SolveAllBoards)struct [boardsPBN](#boardsPBN) \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct [solvedBoards](#solvedBoards) \*solvedpstruct solvedBoards *solvedp
 
[SolveAllChunksBin](#SolveAllChunksBin)struct [boards](#boards) \*bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct [solvedBoards](#solvedBoards) \*solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
 
[SolveAllChunks](#SolveAllChunks)struct [boardsPBN](#boardsPBN) \*bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct [solvedBoards](#solvedBoards) \*solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
 
[SolveAllChunksPBN](#SolveAllChunksPBN)struct [boardsPBN](#boardsPBN) \*bopPBNSolves a number of hands in parallel. Multi-threaded.SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct [solvedBoards](#solvedBoards) \*solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
 
[Par](#Par)struct [ddTableResults](#ddTableResults) \*tablepNo formatSolves for the par contracts given a DD result table.Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.
struct [parResults](#parResults) \*prespstruct parResults *presp
int vulnerableint vulnerable
 
[DealerPar](#DealerPar)struct [ddTableResults](#ddTableResults) \*tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct [parResultsDealer](#parResultsDealer) \*prespstruct parResultsDealer *presp
int dealerint dealer
int vulnerableint vulnerable
 
[DealerParBin](#DealerParBin)struct [ddTableResults](#ddTableResults) \*tablepBinarySimilar to DealerPar, but with binary output.DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.
struct [parResultsMaster](#parResultsMaster) \* prespstruct parResultsMaster * presp
int dealerint dealer
int vulnerableint vulnerable
 
[ConvertToDealerTextFormat](#ConvertToDealerTextFormat)struct [parResultsMaster](#parResultsMaster) \*presTextExample of text output from DealerParBin.ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.
char \*respchar *resp
 
[SidesPar](#SidesPar)struct [ddTableResults](#ddTableResults) \*tablepNo formatPar results are given for sides with the DealerPar output format.SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.
struct [parResultsDealer](#parResultsDealer) \*prespstruct parResultsDealer *presp
int vulnerableint vulnerable
 
[SidesParBin](#SidesParBin)struct [ddTableResults](#ddTableResults) \*tablepBinarySimilar to SidesPar, but with binary output.SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.
struct [parResultsMaster](#parResultsMaster) sidesRes[2]struct parResultsMaster sidesRes[2]
int vulnerableint vulnerable
 
[ConvertToSidesTextFormat](#ConvertToSidesTextFormat)struct [parResultsMaster](#parResultsMaster) \*presTextExample of text output from SidesParBin.ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.
char \*respchar *resp
 
[CalcPar](#CalcPar)struct [ddTableDeal](#ddTableDeal) tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerableint vulnerable
struct [ddTableResults](#ddTabeleResults) \*tablepstruct ddTabeleResults *tablep
struct [parResults](#parResults) \*prespstruct parResults *presp
 
[CalcParPBN](#CalcParPBN)struct [ddTableDealPBN](#ddTableDealPBN) tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct [ddTableResult](#ddTableResults)s \*tablepstruct ddTableResults *tablep
int vulnerableint vulnerable
struct [parResults](#parResults) \*prespstruct parResults *presp
 
[AnalysePlayBin](#AnalysePlayBin)struct [deal](#deal) dlBinaryReturns the par result after each card in a particular play sequence.AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct [playTraceBin](#playTraceBin) playstruct playTraceBin play
struct [solvedPlay](#solvedPlay) \*solvedpstruct solvedPlay *solvedp
int thrIdint thrId
 
[AnalysePlayPBN](#AnalysePlayPBN)struct [dealPBN](#dealPBN) dlPBNPBNAs AnalysePlayBin, but with PBN deal format.AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct [playTracePBN](#playTracePBN) playPBNstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay *solvedp
int thrIdint thrId
 
[AnalyseAllPlaysBin](#AnalyseAllPlaysBin)struct [boards](#boards) \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct [playTracesBi](#playTracesBin)n \*plpstruct playTracesBin *plp
struct [solvedPlays](#solvedPlays) \*solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
 
[AnalyseAllPlaysPBN](#AnalyseAllPlaysPBN)struct [boardsPBN](#boardsPBN) \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct [playTracesPBN](#playTracesPBN) \*plpPBNstruct playTracesPBN *plpPBN
struct [solvedPlay](#solvedPlay)s \*solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
 
[SetMaxThreads](#SetMaxThreads)int userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
[FreeMemory](#FreeMemory)void Frees DDS allocated dynamical memory.FreeMemoryvoid Frees DDS allocated dynamical memory.
 
[ErrorMessage](#ErrorMessage)int code Turns a return code into an error message string.ErrorMessageint code Turns a return code into an error message string.
From d8999fab22c92c67aea199c4b22d576b931f975e Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 03:01:23 +0100 Subject: [PATCH 095/199] Three minor bugs --- doc/dll-description.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index dc29c498..36baf4f0 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -96,7 +96,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablep
 
ErrorMessageint code Turns a return code into an error message string.ErrorMessageint code Turns a return code into an error message string.
From d08d0804a069485a187aad25e1be3761e04682cf Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 04:20:11 +0100 Subject: [PATCH 096/199] Playing with non-bring-spaces --- doc/dll-description.md | 70 +++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 36baf4f0..5b179402 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,40 +59,40 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later playSolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int targetint target
int solutionsint solutions
int modeint mode
struct futureTricks *futpstruct futureTricks *futp
int threadIndex
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int targetint target
int solutionsint solutions
int modeint mode
struct futureTricks *futpstruct futureTricks *futp
int threadIndexint threadIndex
 
Rev A2006-02-25First issue
Rev B2006-03-20Updated issueRev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to playRev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parametersRev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutionsRev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRankRev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread supportRev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar dealsRev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer handRev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBNRev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. +Rev M2012-07-06Added SolveAllBoards. Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBNRev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBNRev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBNRev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBNRev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunksRev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From bae49f96cef2bc4490713124ba591befa4dd544e Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 04:37:26 +0100 Subject: [PATCH 097/199] Trying with inline css --- doc/dll-description.md | 141 ++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 71 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 5b179402..88bb62a2 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -54,7 +54,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -73,7 +73,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -96,239 +96,239 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -336,7 +336,6 @@ of the dealer. - From af46f6548b2907c4745e5ea9ce2bac0d3663f4ea Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 04:39:51 +0100 Subject: [PATCH 098/199] Oops, trying with white-space:nowrap; --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 88bb62a2..2a30f35b 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -54,7 +54,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal
FunctionArgumentsFormatCommentFunctionArgumentsFormatComment
struct futureTricks *futp
int threadIndex
int threadIndex
 
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablepstruct ddTableResults *tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablepstruct ddTableResults *tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddtablesRes *respstruct ddtablesRes *resp
struct allParResultsa> *presstruct allParResultsa> *pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.CalcAllTablesPBNstruct  ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *resp
struct allParResults *presstruct allParResults *pres
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedpstruct solvedBoards *solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded.SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSize
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *prespstruct parResults *presp
int vulnerableint vulnerable
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *prespstruct parResultsDealer *presp
int dealerint dealer
int vulnerableint vulnerable
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster * prespstruct parResultsMaster *presp
int dealerint dealer
int vulnerableint vulnerable
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.
char *respchar *resp
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *prespstruct parResultsDealer *presp
int vulnerableint vulnerable
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]struct parResultsMaster sidesRes[2]
int vulnerable
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.
char *respchar *resp
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerableint vulnerable
struct ddTabeleResults *tablepstruct ddTabeleResults *tablep
struct parResults *prespstruct parResults *presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablepstruct ddTableResults *tablep
int vulnerableint vulnerable
struct parResults *prespstruct parResults *presp
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin playstruct playTraceBin play
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBNstruct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plpstruct playTracesBin *plp
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBNstruct playTracesPBN *plpPBN
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
 
ErrorMessageint code Turns a return code into an error message string.
- + From 4038a4020b794e3b2dbe06e31238faef42cede81 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 05:12:25 +0100 Subject: [PATCH 099/199] Trying to get rid of zebra stripes through inline css --- doc/dll-description.md | 826 ++++++++++++++++++++--------------------- 1 file changed, 413 insertions(+), 413 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 2a30f35b..0f00a723 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -53,291 +53,291 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal
FunctionArgumentsFormatCommentFunctionArgumentsFormatComment
- + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - - + + - + - - + + - + - + - + - - + + - - + + - + - + - + - + - - + + - + - - + + - + - + - - + + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - - + + - + - + - - + + - + - + - - + + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - - + + - - + + - +
FunctionArgumentsFormatComment
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
int solutions
int mode
struct futureTricks *futp
int threadIndex
int threadIndex
 
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int solutions
int mode
struct futureTricks *futp
int threadIndex
 
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults *tablep
 
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults *tablep
 
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddtablesRes *resp
struct allParResultsa> *pres
struct allParResults *pres
 
 
CalcAllTablesPBNstruct  ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedp
 
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *presp
int vulnerable
 
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *presp
int dealer
int vulnerable
 
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster *presp
int dealer
int vulnerable
 
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.
char *resp
 
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *presp
int vulnerable
 
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
int vulnerable
 
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.
char *resp
 
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTabeleResults *tablep
struct parResults *presp
 
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablep
int vulnerable
struct parResults *presp
 
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
struct solvedPlay *solvedp
int thrId
 
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
struct solvedPlay *solvedp
int thrId
 
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plp
struct solvedPlays *solvedp
int chunkSize
 
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBN
struct solvedPlays *solvedp
int chunkSize
 
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
 
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
 
@@ -346,56 +346,56 @@ Common encodings are as follows - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -403,356 +403,356 @@ Common encodings are as follows
EncodingElementValue
SuitSpades0
Hearts1
Hearts1
Diamonds2
Clubs3
NT4
 
 
HandNorth0
East1
East1
South2
West3
 
 
SideN-S0
E-W1
E-W1
 
 
CardBit 2Rank of deuce
... 
... 
Bit 13Rank of king
Bit 14Rank of ace
 
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + @@ -762,27 +762,27 @@ Common encodings are as follows
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
StructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
StructFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
StructFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
StructFieldComment
parTextResultschar parText[2][128];
int equal;
StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
StructFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
StructFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
StructFieldComment
solvedPlayint number;
int tricks[53];Starting position and up to 52 cards
StructFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- + - + - + - + - + - + - + @@ -804,52 +804,52 @@ For equivalent cards, only the highest is returned, and lower equivalent cards a
SolveBoardSolveBoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
- + - + - + - + - + - + - + - + - + - + - + - + @@ -871,43 +871,43 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure
targetsolutionscomment
-11Find the maximum number of tricks for the side to play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with score set to 0.
02Return all cards that legal to play, with score set to 0.
1 .. 131If score is -1: Target cannot be reached.
If score is 0: In fact no tricks at all can be won.
If score is > 0: score will always equal target, even if more tricks can be won.
One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
- + - + - +
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablep
CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “\*tablep” , which must be declared before calling CalcDDtable. - + - + - + - + - + - + @@ -925,24 +925,24 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults \*prespstruct allParResults \*presp
- + - + - + - + - + - + @@ -950,18 +950,18 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
Number of strainsMaximum number of DD tables
532
440
353
280
1160
- + - + - + - + @@ -985,66 +985,66 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or
SolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp
int chunkSizeint chunkSize
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1094,21 +1094,21 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding.
ParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResults \*prespstruct parResultsDealer \*presp
int vulnerableint dealer
 int vulnerable
 
SidesPar 
struct ddTableResults \*tablep 
struct parResultsDealer \*sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResultsMaster \* prespstruct parResultsMaster \* presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
char \*respstruct parTextResults \*resp
- + - + - + - + - + @@ -1122,21 +1122,21 @@ Both functions are deprecated. Instead use one of the CalcDDtable functions foll
CalcParCalcParPBN
struct ddTableDeal dlstruct ddTableDealPBN dlN
int vulnerablestruct ddTableResults * tp
struct ddTableResults * tpint vulnerable
struct parResults *prespstruct parResults *presp
- + - + - + - + - + @@ -1154,21 +1154,21 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedp
int thrIdint thrId
- + - + - + - + - + @@ -1182,12 +1182,12 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedp
int chunkSizeint chunkSize
- + - + @@ -1214,87 +1214,87 @@ It is possible to ask DDS to give up its dynamically allocated memory by calling
SetMaxThreadsFreeMemory
int userThreadsvoid
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1302,84 +1302,84 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
- + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + - - + - - + +
Revision History
Rev A2006-02-25First issue
Rev A2006‑02‑25First issue
Rev B2006-03-20Updated issue
Rev B2006‑03‑20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev C2006‑03‑28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev D2006‑04‑05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev E2006‑05‑29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F2006‑08‑09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F12006‑08‑14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev F22006‑08‑26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev G2007‑01‑04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev H2007‑04‑23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev I2010‑04‑10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev J2010‑05‑29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev K2010‑10‑27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev L2011‑10‑14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. -Rev N, 2012-07-16 Max number of threads is 8
Rev M2012‑07‑06Added SolveAllBoards. +Rev N, 2012‑07‑16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev O2012‑10‑21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev P2013‑03‑16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev Q2014‑01‑09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev R2014‑01‑13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014‑01‑13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev T2014‑03‑01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +
Rev U2014‑09‑15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +
Rev V2014‑10‑14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
Rev X2014‑11‑16Extended maximum number of tables when calling CalcAllTables.
From 922fdb3d20270b57ca18025b0d53343b4eb41efe Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 05:16:31 +0100 Subject: [PATCH 100/199] UNDO: Trying to get rid of zebra stripes through inline css --- doc/dll-description.md | 772 ++++++++++++++++++++--------------------- 1 file changed, 386 insertions(+), 386 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 0f00a723..d5d236af 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -53,291 +53,291 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - - + + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - - + + - + - + - - + + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - - + + - + - + - - + + - + - + - - + + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - - + + - - + + - +
FunctionArgumentsFormatComment
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
int solutions
int mode
struct futureTricks *futp
int threadIndex
int threadIndex
 
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int solutions
int mode
struct futureTricks *futp
int threadIndex
 
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults *tablep
 
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults *tablep
 
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddtablesRes *resp
struct allParResults *pres
 
 
CalcAllTablesPBNstruct  ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedp
 
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *presp
int vulnerable
 
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *presp
int dealer
int vulnerable
 
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster *presp
int dealer
int vulnerable
 
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.
char *resp
 
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *presp
int vulnerable
 
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
int vulnerable
 
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.
char *resp
 
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTabeleResults *tablep
struct parResults *presp
 
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablep
int vulnerable
struct parResults *presp
 
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
struct solvedPlay *solvedp
int thrId
 
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
struct solvedPlay *solvedp
int thrId
 
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plp
struct solvedPlays *solvedp
int chunkSize
 
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBN
struct solvedPlays *solvedp
int chunkSize
 
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
 
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
 
@@ -346,56 +346,56 @@ Common encodings are as follows - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -403,356 +403,356 @@ Common encodings are as follows
EncodingElementValue
SuitSpades0
Hearts1
Hearts1
Diamonds2
Clubs3
NT4
 
 
HandNorth0
East1
East1
South2
West3
 
 
SideN-S0
E-W1
E-W1
 
 
CardBit 2Rank of deuce
... 
... 
Bit 13Rank of king
Bit 14Rank of ace
 
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + @@ -762,27 +762,27 @@ Common encodings are as follows
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
StructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
StructFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
StructFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
StructFieldComment
parTextResultschar parText[2][128];
int equal;
StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
StructFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
StructFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
StructFieldComment
solvedPlayint number;
int tricks[53];Starting position and up to 52 cards
StructFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- + - + - + - + - + - + - + @@ -804,52 +804,52 @@ For equivalent cards, only the highest is returned, and lower equivalent cards a
SolveBoardSolveBoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
- + - + - + - + - + - + - + - + - + - + - + - + @@ -871,15 +871,15 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure
targetsolutionscomment
-11Find the maximum number of tricks for the side to play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with score set to 0.
02Return all cards that legal to play, with score set to 0.
1 .. 131If score is -1: Target cannot be reached.
If score is 0: In fact no tricks at all can be won.
If score is > 0: score will always equal target, even if more tricks can be won.
One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
- + - + - + @@ -890,24 +890,24 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablep
- + - + - + - + - + - + @@ -925,24 +925,24 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults \*prespstruct allParResults \*presp
- + - + - + - + - + - + @@ -950,18 +950,18 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
Number of strainsMaximum number of DD tables
532
440
353
280
1160
- + - + - + - + @@ -985,66 +985,66 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or
SolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp
int chunkSizeint chunkSize
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1094,21 +1094,21 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding.
ParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResults \*prespstruct parResultsDealer \*presp
int vulnerableint dealer
 int vulnerable
 
SidesPar 
struct ddTableResults \*tablep 
struct parResultsDealer \*sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResultsMaster \* prespstruct parResultsMaster \* presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
char \*respstruct parTextResults \*resp
- + - + - + - + - + @@ -1122,21 +1122,21 @@ Both functions are deprecated. Instead use one of the CalcDDtable functions foll
CalcParCalcParPBN
struct ddTableDeal dlstruct ddTableDealPBN dlN
int vulnerablestruct ddTableResults * tp
struct ddTableResults * tpint vulnerable
struct parResults *prespstruct parResults *presp
- + - + - + - + - + @@ -1154,21 +1154,21 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedp
int thrIdint thrId
- + - + - + - + - + @@ -1182,12 +1182,12 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedp
int chunkSizeint chunkSize
- + - + @@ -1214,87 +1214,87 @@ It is possible to ask DDS to give up its dynamically allocated memory by calling
SetMaxThreadsFreeMemory
int userThreadsvoid
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1302,84 +1302,84 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
Revision History
Rev A2006‑02‑25First issue
Rev B2006‑03‑20Updated issue
Rev C2006‑03‑28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006‑04‑05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006‑05‑29Updated issue. New error code –10 for number of cards > 52
Rev F2006‑08‑09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006‑08‑14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006‑08‑26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007‑01‑04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007‑04‑23DDS release 1.4, changes for parameter mode=2.
Rev I2010‑04‑10DDS release 2.0, multi-thread support
Rev J2010‑05‑29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010‑10‑27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011‑10‑14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012‑07‑06Added SolveAllBoards. Rev N, 2012‑07‑16 Max number of threads is 8
Rev O2012‑10‑21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013‑03‑16Added functions CalcPar and CalcParPBN
Rev Q2014‑01‑09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014‑01‑13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014‑01‑13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014‑03‑01Added function SolveAllChunks
Rev U2014‑09‑15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, AnalyseAllPlaysPBN
Rev V2014‑10‑14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014‑11‑16Extended maximum number of tables when calling CalcAllTables.
From 6d485417aae3008c32b490ed45fa210383dd814e Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 05:21:52 +0100 Subject: [PATCH 101/199] UNDO: nbsp; in tables --- doc/dll-description.md | 212 ++++++++++++++++++++--------------------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index d5d236af..e7cb78ed 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,282 +59,282 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play -int target +int target -int solutions +int solutions -int mode +int mode -struct futureTricks *futp +struct futureTricks *futp -int threadIndex +int threadIndex -  + -SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. +SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. -int target +int target -int solutions +int solutions -int mode +int mode -struct futureTricks *futp +struct futureTricks *futp -int threadIndex +int threadIndex -  + -CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) +CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) -struct ddTableResults *tablep +struct ddTableResults *tablep -  + -CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. +CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. -struct ddTableResults *tablep +struct ddTableResults *tablep -  + -CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded. +CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded. -int mode +int mode -int trumpFilter[5] +int trumpFilter[5] -struct ddtablesRes *resp +struct ddtablesRes *resp -struct allParResults *pres +struct allParResults *pres -  + -CalcAllTablesPBNstruct  ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format. +CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format. -int mode +int mode -int trumpFilter[5] +int trumpFilter[5] -struct ddTablesRes *resp +struct ddTablesRes *resp -struct allParResults *pres +struct allParResults *pres -  + -SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! +SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! -struct solvedBoards *solvedp +struct solvedBoards *solvedp -  + -SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. -struct solvedBoards *solvedp +struct solvedBoards *solvedp -int chunkSize +int chunkSize -  + -SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! -struct solvedBoards *solvedp +struct solvedBoards *solvedp int chunkSize -  + -SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded. -struct solvedBoards *solvedp +struct solvedBoards *solvedp int chunkSize -  + -Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. +Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. -struct parResults *presp +struct parResults *presp -int vulnerable +int vulnerable -  + -DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer. -struct parResultsDealer *presp +struct parResultsDealer *presp -int dealer +int dealer -int vulnerable +int vulnerable -  + -DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. +DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. -struct parResultsMaster *presp +struct parResultsMaster *presp -int dealer +int dealer -int vulnerable +int vulnerable -  + -ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. +ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. -char *resp +char *resp -  + -SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. +SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. -struct parResultsDealer *presp +struct parResultsDealer *presp -int vulnerable +int vulnerable -  + -SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. +SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. -struct parResultsMaster sidesRes[2] +struct parResultsMaster sidesRes[2] int vulnerable -  + -ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. +ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. -char *resp +char *resp -  + -CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! -int vulnerable +int vulnerable -struct ddTabeleResults *tablep +struct ddTabeleResults *tablep -struct parResults *presp +struct parResults *presp -  + -CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! -struct ddTableResults *tablep +struct ddTableResults *tablep -int vulnerable +int vulnerable -struct parResults *presp +struct parResults *presp -  + -AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. -struct playTraceBin play +struct playTraceBin play -struct solvedPlay *solvedp +struct solvedPlay *solvedp -int thrId +int thrId -  + -AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. -struct playTracePBN playPBN +struct playTracePBN playPBN -struct solvedPlay *solvedp +struct solvedPlay *solvedp -int thrId +int thrId -  + -AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. +AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. -struct playTracesBin *plp +struct playTracesBin *plp -struct solvedPlays *solvedp +struct solvedPlays *solvedp -int chunkSize +int chunkSize -  + -AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. +AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. -struct playTracesPBN *plpPBN +struct playTracesPBN *plpPBN -struct solvedPlays *solvedp +struct solvedPlays *solvedp -int chunkSize +int chunkSize -  + -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) -  + -FreeMemoryvoid Frees DDS allocated dynamical memory. +FreeMemoryvoid Frees DDS allocated dynamical memory. -  + From c1442aabae3dd805ac37d1de8a12dbbd1158fbe3 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 05:24:00 +0100 Subject: [PATCH 102/199] UNDO: Style in table --- doc/dll-description.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index e7cb78ed..69471027 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -54,7 +54,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -335,9 +335,6 @@ of the dealer. - - -
FunctionArgumentsFormatCommentFunctionArgumentsFormatComment
FreeMemoryvoid Frees DDS allocated dynamical memory.
From fc0d9dceb466daecc18793a8efcca5beaea8a1e1 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 05:26:55 +0100 Subject: [PATCH 103/199] REDO:   in tables --- doc/dll-description.md | 212 ++++++++++++++++++++--------------------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 69471027..4b9036e7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,282 +59,282 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play -int target +int target -int solutions +int solutions -int mode +int mode -struct futureTricks *futp +struct futureTricks *futp -int threadIndex +int threadIndex - +  -SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. +SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. -int target +int target -int solutions +int solutions -int mode +int mode -struct futureTricks *futp +struct futureTricks *futp -int threadIndex +int threadIndex - +  -CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) +CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) -struct ddTableResults *tablep +struct ddTableResults *tablep - +  -CalcDDtablePBN
struct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. +CalcDDtablePBN
struct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. -struct ddTableResults *tablep +struct ddTableResults *tablep - +  -CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded. +CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded. -int mode +int mode -int trumpFilter[5] +int trumpFilter[5] -struct ddtablesRes *resp +struct ddtablesRes *resp -struct allParResults *pres +struct allParResults *pres - +  -CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format. +CalcAllTablesPBNstruct  ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format. -int mode +int mode -int trumpFilter[5] +int trumpFilter[5] -struct ddTablesRes *resp +struct ddTablesRes *resp -struct allParResults *pres +struct allParResults *pres - +  -SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! +SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! -struct solvedBoards *solvedp +struct solvedBoards *solvedp - +  -SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. -struct solvedBoards *solvedp +struct solvedBoards *solvedp -int chunkSize +int chunkSize - +  -SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! -struct solvedBoards *solvedp +struct solvedBoards *solvedp int chunkSize - +  -SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded. -struct solvedBoards *solvedp +struct solvedBoards *solvedp int chunkSize - +  -Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. +Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. -struct parResults *presp +struct parResults *presp -int vulnerable +int vulnerable - +  -DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer. -struct parResultsDealer *presp +struct parResultsDealer *presp -int dealer +int dealer -int vulnerable +int vulnerable - +  -DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. +DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. -struct parResultsMaster *presp +struct parResultsMaster *presp -int dealer +int dealer -int vulnerable +int vulnerable - +  -ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. +ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. -char *resp +char *resp - +  -SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. +SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. -struct parResultsDealer *presp +struct parResultsDealer *presp -int vulnerable +int vulnerable - +  -SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. +SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. -struct parResultsMaster sidesRes[2] +struct parResultsMaster sidesRes[2] int vulnerable - +  -ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. +ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. -char *resp +char *resp - +  -CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! -int vulnerable +int vulnerable -struct ddTabeleResults *tablep +struct ddTabeleResults *tablep -struct parResults *presp +struct parResults *presp - +  -CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! -struct ddTableResults *tablep +struct ddTableResults *tablep -int vulnerable +int vulnerable -struct parResults *presp +struct parResults *presp - +  -AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. -struct playTraceBin play +struct playTraceBin play -struct solvedPlay *solvedp +struct solvedPlay *solvedp -int thrId +int thrId - +  -AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. -struct playTracePBN playPBN +struct playTracePBN playPBN -struct solvedPlay *solvedp +struct solvedPlay *solvedp -int thrId +int thrId - +  -AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. +AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. -struct playTracesBin *plp +struct playTracesBin *plp -struct solvedPlays *solvedp +struct solvedPlays *solvedp -int chunkSize +int chunkSize - +  -AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. +AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. -struct playTracesPBN *plpPBN +struct playTracesPBN *plpPBN -struct solvedPlays *solvedp +struct solvedPlays *solvedp -int chunkSize +int chunkSize - +  -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) - +  -FreeMemoryvoid Frees DDS allocated dynamical memory. +FreeMemoryvoid Frees DDS allocated dynamical memory. - +  From 62e1f4d63f79d402e040a6438f2c7091f87e58c2 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 06:18:09 +0100 Subject: [PATCH 104/199] tags in Data structure table --- doc/dll-description.md | 131 ++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 66 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 4b9036e7..9f6f1fc5 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -334,7 +334,6 @@ of the dealer. FreeMemoryvoid Frees DDS allocated dynamical memory. -  @@ -406,19 +405,19 @@ Common encodings are as follows -dealint trump;Suit encoding +dealint trumpSuit encoding -int first;The hand leading to the trick. Hand encoding. +int firstThe hand leading to the trick. Hand encoding. -int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. +int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. -int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. +int currentTrickRank[3]Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. +unsigned int remainCards[4][4]1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. @@ -427,19 +426,19 @@ Common encodings are as follows structFieldComment -dealPBNint trump;Suit encoding +dealPBNint trumpSuit encoding -int first;The hand leading to the trick. Hand encoding. +int firstThe hand leading to the trick. Hand encoding. -int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played. +int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played. -int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. +int currentTrickRank[3]Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -char remainCards[80];Remaining cards. PBN encoding. +char remainCards[80]Remaining cards. PBN encoding. @@ -449,7 +448,7 @@ Common encodings are as follows structFieldComment -ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding +ddTableDealunsigned int cards[4][4]Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding @@ -459,10 +458,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES +ddTableDealsint noOfTablesNumber of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS +struct ddTableDeal deals[X]X = MAXNOOFTABLES * DDS_STRAINS @@ -472,10 +471,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTables;Number of DD table deals in structure +ddTableDealsint noOfTablesNumber of DD table deals in structure -struct ddTableDealPBN deals[MAXNOOFBOARDS/4]; +struct ddTableDealPBN deals[MAXNOOFBOARDS/4] @@ -485,19 +484,19 @@ Common encodings are as follows structFieldComment -boardsint noOfBoards;Number of boards +boardsint noOfBoardsNumber of boards -struct deal[MAXNOOFBOARDS]; +struct deal[MAXNOOFBOARDS] -int target[MAXNOOFBOARDS];See SolveBoard +int target[MAXNOOFBOARDS]See SolveBoard -int solutions[MAXNOOFBOARDS];See SolveBoard +int solutions[MAXNOOFBOARDS]See SolveBoard -int mode[MAXNOOFBOARDS];See SolveBoard +int mode[MAXNOOFBOARDS]See SolveBoard @@ -507,19 +506,19 @@ Common encodings are as follows structFieldComment -boardsPBNint noOfBoards;Number of boards +boardsPBNint noOfBoardsNumber of boards -struct dealPBN[MAXNOOFBOARDS]; +struct dealPBN[MAXNOOFBOARDS] -int target[MAXNOOFBOARDS];See SolveBoard +int target[MAXNOOFBOARDS]See SolveBoard -int solutions[MAXNOOFBOARDS];See SolveBoard +int solutions[MAXNOOFBOARDS]See SolveBoard -int mode[MAXNOOFBOARDS];See SolveBoard +int mode[MAXNOOFBOARDS]See SolveBoard @@ -528,22 +527,22 @@ Common encodings are as follows structFieldComment -futureTricksint nodes;Number of nodes searched by the DD solver. +futureTricksint nodesNumber of nodes searched by the DD solver. -int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7. +int cardsNumber of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7. -int suit[13];Suit of the each returned card. Suit encoding. +int suit[13]Suit of the each returned card. Suit encoding. -int rank[13];Rank of the returned card. Value range 2-14. +int rank[13]Rank of the returned card. Value range 2-14. -int equals[13];Lower-ranked equals. Holding encoding. +int equals[13]Lower-ranked equals. Holding encoding. -int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks. +int score[13]-1: target not reached. Otherwise: Target of maximum number of tricks. @@ -553,10 +552,10 @@ Common encodings are as follows structFieldComment -solvedBoardsint noOfBoards; +solvedBoardsint noOfBoards -struct futureTricks solvedBoard [MAXNOOFBOARDS]; +struct futureTricks solvedBoard [MAXNOOFBOARDS] @@ -566,7 +565,7 @@ Common encodings are as follows StructFieldComment -ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. +ddTableResultsint resTable[5][4]Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. @@ -576,10 +575,10 @@ Common encodings are as follows structFieldComment -ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES +ddTablesResint noOfBoardsNumber of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS +struct ddTableResults results[X]X = MAXNOOFTABLES \* DDS_STRAINS @@ -589,10 +588,10 @@ Common encodings are as follows StructFieldComment -parResultschar parScore[2][16];First index is NS/EW. Side encoding. +parResultschar parScore[2][16]First index is NS/EW. Side encoding. -char parContractsString[2][128];First index is NS/EW. Side encoding. +char parContractsString[2][128]First index is NS/EW. Side encoding. @@ -602,7 +601,7 @@ Common encodings are as follows StructFieldComment -allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table +allParResultsstruct parResults[MAXNOOFTABLES]There are up to 20 declarer/strain combinations per DD table @@ -612,13 +611,13 @@ Common encodings are as follows StructFieldComment -parResultsDealerint number; +parResultsDealerint number -int score; +int score -char contracts[10][10]; +char contracts[10][10] @@ -628,13 +627,13 @@ Common encodings are as follows StructFieldComment -parResultsMasterint score; +parResultsMasterint score -int number; +int number -struct contractType contracts[10]; +struct contractType contracts[10] @@ -644,19 +643,19 @@ Common encodings are as follows StructFieldComment -contractTypeint underTricks; +contractTypeint underTricks -int overTricks; +int overTricks -int level; +int level -int denom; +int denom -int seats; +int seats @@ -666,10 +665,10 @@ Common encodings are as follows StructFieldComment -parTextResultschar parText[2][128]; +parTextResultschar parText[2][128] -int equal; +int equal @@ -679,13 +678,13 @@ Common encodings are as follows StructFieldComment -playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand. +playTraceBinint numberNumber of cards in the play trace, starting from the beginning of the hand. -int suit[52];Suit encoding. +int suit[52]Suit encoding. -int rank[52];Encoding 2 .. 14 (not Card encoding). +int rank[52]Encoding 2 .. 14 (not Card encoding). @@ -695,10 +694,10 @@ Common encodings are as follows StructFieldComment -playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand. +playTracePBNint numberNumber of cards in the play trace, starting from the beginning of the hand. -int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated. +int cards[106]String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated. @@ -708,10 +707,10 @@ Common encodings are as follows StructFieldComment -playTracesBinint noOfBoards; +playTracesBinint noOfBoards -struct playTraceBin plays[MAXNOOFBOARDS / 10]; +struct playTraceBin plays[MAXNOOFBOARDS / 10] @@ -721,10 +720,10 @@ Common encodings are as follows StructFieldComment -playTracesPBNint noOfBoards; +playTracesPBNint noOfBoards -struct playTracePBN plays[MAXNOOFBOARDS / 10]; +struct playTracePBN plays[MAXNOOFBOARDS / 10] @@ -734,10 +733,10 @@ Common encodings are as follows StructFieldComment -solvedPlayint number; +solvedPlayint number -int tricks[53];Starting position and up to 52 cards +int tricks[53];Starting position and up to 52 cards @@ -747,10 +746,10 @@ Common encodings are as follows StructFieldComment -solvedPlaysint noOfBoards; +solvedPlaysint noOfBoards -struct solvedPlay solved[MAXNOOFBOARDS]; +struct solvedPlay solved[MAXNOOFBOARDS] From a8ccef40b2b93d8d7084778ae8dccdc34c6ab70b Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 06:21:05 +0100 Subject: [PATCH 105/199] Last commit for the day --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 9f6f1fc5..fe54960c 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -643,7 +643,7 @@ Common encodings are as follows StructFieldComment -contractTypeint underTricks +contractTypeint underTricks int overTricks From e97abd0ad0f5ad68b54c9456f001dc9bb45ce7ff Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 22:25:33 +0100 Subject: [PATCH 106/199] Added tags in functions --- doc/dll-description.md | 108 ++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index fe54960c..b253ec37 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -759,27 +759,27 @@ Common encodings are as follows - + - + - + - + - + - + - +
SolveBoardSolveBoardPBNSolveBoardSolveBoardPBN
struct deal dl,struct dealPBN dl,struct deal dlstruct dealPBN dl
int target,int target,int targetint target
int solutions,int solutions,int solutionsint solutions
int mode,int mode,int modeint mode
struct futureTricks \*futp,struct futureTricks \*futp,struct futureTricks *futpstruct futureTricks *futp
int threadIndexint threadIndexint threadIndexint threadIndex
@@ -868,15 +868,15 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure - + - + - +
CalcDDtableCalcDDtablePBNCalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBNstruct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablepstruct ddTableResults *tablepstruct ddTableResults *tablep
@@ -887,24 +887,24 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + - + - + - + - + - +
CalcAllTablesCalcAllTablesPBNCalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealspstruct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp
int modeint modeint modeint mode
int trumpFilter[5]int trumpFilter[5]int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*respstruct ddTablesRes *respstruct ddTablesRes *resp
struct allParResults \*prespstruct allParResults \*prespstruct allParResults *prespstruct allParResults *presp
@@ -947,18 +947,18 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + - +
SolveAllBoardsSolveAllChunksBinSolveAllChunksPBNSolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bopstruct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSizeint chunkSizeint chunkSize
@@ -982,66 +982,66 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
ParDealerParParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablepstruct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults \*prespstruct parResultsDealer \*prespstruct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealerint vulnerableint dealer
 int vulnerable int vulnerable
 
SidesPar SidesPar 
struct ddTableResults \*tablep struct ddTableResults *tablep 
struct parResultsDealer \*sidesRes[2] struct parResultsDealer *sidesRes[2] 
int vulnerable int vulnerable 
 
DealerParBinSidesParBinDealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablepstruct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster \* prespstruct parResultsMaster \* prespstruct parResultsMaster *prespstruct parResultsMaster *presp
int vulnerableint dealerint vulnerableint dealer
 int vulnerable int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormatConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*presstruct parResultsMaster *presstruct parResultsMaster *pres
char \*respstruct parTextResults \*respchar *respstruct parTextResults *resp
@@ -1091,21 +1091,21 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding. - + - + - + - + - +
CalcParCalcParPBNCalcParCalcParPBN
struct ddTableDeal dlstruct ddTableDealPBN dlNstruct ddTableDeal dlstruct ddTableDealPBN dlN
int vulnerablestruct ddTableResults * tpint vulnerablestruct ddTableResults *tp
struct ddTableResults * tpint vulnerablestruct ddTableResults *tpint vulnerable
struct parResults *prespstruct parResults *prespstruct parResults *prespstruct parResults *presp
@@ -1119,21 +1119,21 @@ Both functions are deprecated. Instead use one of the CalcDDtable functions foll - + - + - + - + - +
AnalysePlayBinAnalysePlayPBNAnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBNstruct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBNstruct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedpstruct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrIdint thrIdint thrId
@@ -1151,21 +1151,21 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one - + - + - + - + - +
AnalyseAllPlaysBinAnalyseAllPlaysPBNAnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBNstruct boards *bopstruct boardsPBN *bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBNstruct playTracesBin *plpstruct playTracesPBN *plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedpstruct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSizeint chunkSizeint chunkSize
@@ -1179,12 +1179,12 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi - + - +
SetMaxThreadsFreeMemorySetMaxThreadsFreeMemory
int userThreadsvoidint userThreadsvoid
From 3ccb808fefb419bcd699fd4d2dbed66da54e1f51 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 23 Dec 2014 02:09:44 +0100 Subject: [PATCH 107/199] Added last tags in functions --- doc/dll-description.md | 56 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index b253ec37..34abef42 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -764,7 +764,7 @@ Common encodings are as follows -struct deal dlstruct dealPBN dl +struct deal dlstruct dealPBN dl int targetint target @@ -776,7 +776,7 @@ Common encodings are as follows int modeint mode -struct futureTricks *futpstruct futureTricks *futp +struct futureTricks *futpstruct futureTricks *futp int threadIndexint threadIndex @@ -873,10 +873,10 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure -struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN +struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBNddTableDealPBN"> -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults *tablepstruct ddTableResults *tablep @@ -892,7 +892,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy -struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp +struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp int modeint mode @@ -901,10 +901,10 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy int trumpFilter[5]int trumpFilter[5] -struct ddTablesRes *respstruct ddTablesRes *resp - +struct ddTablesRes *respstruct ddTablesRes *resp +ddTablesRes"> -struct allParResults *prespstruct allParResults *presp +<struct allParResults *presp
struct allParResults *presp @@ -947,15 +947,15 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + @@ -987,10 +987,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + - + @@ -1005,10 +1005,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + - + @@ -1020,10 +1020,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + - + @@ -1038,10 +1038,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + - +
SolveAllBoardsSolveAllChunksBinSolveAllChunksPBNSolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boards *bopstruct boardsPBN *bopstruct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
struct ddTableResults *tablepstruct ddTableResults *tablepstruct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults *prespstruct parResultsDealer *prespstruct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealerSidesPar 
struct ddTableResults *tablep struct ddTableResults *tablep 
struct parResultsDealer *sidesRes[2] struct parResultsDealer *sidesRes[2] 
int vulnerable DealerParBinSidesParBin
struct ddTableResults *tablepstruct ddTableResults *tablepstruct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster *prespstruct parResultsMaster *prespstruct parResultsMaster *prespstruct parResultsMaster *presp
int vulnerableint dealerConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster *presstruct parResultsMaster *presstruct parResultsMaster *presstruct parResultsMaster *pres
char *respstruct parTextResults *respchar *respstruct parTextResults *resp
@@ -1096,16 +1096,16 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding. -struct ddTableDeal dlstruct ddTableDealPBN dlN +struct ddTableDeal dlstruct ddTableDealPBN dlN -int vulnerablestruct ddTableResults *tp +int vulnerablestruct ddTableResults *tp -struct ddTableResults *tpint vulnerable +struct ddTableResults *tpint vulnerable -struct parResults *prespstruct parResults *presp +struct parResults *prespstruct parResults *presp @@ -1127,10 +1127,10 @@ Both functions are deprecated. Instead use one of the CalcDDtable functions foll struct deal dlstruct dealPBN dlPBN -struct playTraceBin playstruct playTracePBN playPBN +struct playTraceBin playstruct playTracePBN playPBN -struct solvedPlay *solvedpstruct solvedPlay *solvedp +struct solvedPlay *solvedpstruct solvedPlay *solvedp int thrIdint thrId @@ -1156,13 +1156,13 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one -struct boards *bopstruct boardsPBN *bopPBN +struct boards *bopstruct boardsPBN *bopPBN -struct playTracesBin *plpstruct playTracesPBN *plpPBN +struct playTracesBin *plpstruct playTracesPBN *plpPBN -struct solvedPlays *solvedpstruct solvedPlays *solvedp +struct solvedPlays *solvedpstruct solvedPlays *solvedp int chunkSizeint chunkSize From 7c1f322ad9fd07bcb606022a4dbe96f5dbb5d440 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 23 Dec 2014 02:31:16 +0100 Subject: [PATCH 108/199] Added all links --- doc/dll-description.md | 78 ++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 34abef42..4a4096ff 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -405,19 +405,19 @@ Common encodings are as follows -dealint trumpSuit encoding +dealint trumpSuit encoding -int firstThe hand leading to the trick. Hand encoding. +int firstThe hand leading to the trick. Hand encoding. -int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. +int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. int currentTrickRank[3]Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -unsigned int remainCards[4][4]1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. +unsigned int remainCards[4][4]1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. @@ -426,19 +426,19 @@ Common encodings are as follows structFieldComment -dealPBNint trumpSuit encoding +dealPBNint trumpSuit encoding -int firstThe hand leading to the trick. Hand encoding. +int firstThe hand leading to the trick. Hand encoding. -int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played. +int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played. int currentTrickRank[3]Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -char remainCards[80]Remaining cards. PBN encoding. +char remainCards[80]Remaining cards. PBN encoding. @@ -448,7 +448,7 @@ Common encodings are as follows structFieldComment -ddTableDealunsigned int cards[4][4]Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding +ddTableDealunsigned int cards[4][4]Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. @@ -458,7 +458,17 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTablesNumber of DD table deals in structure, at most MAXNOOFTABLES +ddTableDealPBNchar cards[80]Encodes a deal. PBN encoding. + + + + + + +structFieldComment + + +ddTableDealsint noOfTablesNumber of DD table deals in structure, at most MAXNOOFTABLES struct ddTableDeal deals[X]X = MAXNOOFTABLES * DDS_STRAINS @@ -471,10 +481,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTablesNumber of DD table deals in structure +ddTableDealsPBNint noOfTablesNumber of DD table deals in structure -struct ddTableDealPBN deals[MAXNOOFBOARDS/4] +struct ddTableDealPBN deals[X]X = MAXNOOFTABLES * DDS_STRAINS @@ -490,13 +500,13 @@ Common encodings are as follows struct deal[MAXNOOFBOARDS] -int target[MAXNOOFBOARDS]See SolveBoard +int target[MAXNOOFBOARDS]See SolveBoard -int solutions[MAXNOOFBOARDS]See SolveBoard +int solutions[MAXNOOFBOARDS]See SolveBoard -int mode[MAXNOOFBOARDS]See SolveBoard +int mode[MAXNOOFBOARDS]See SolveBoard @@ -512,13 +522,13 @@ Common encodings are as follows struct dealPBN[MAXNOOFBOARDS] -int target[MAXNOOFBOARDS]See SolveBoard +int target[MAXNOOFBOARDS]See SolveBoard -int solutions[MAXNOOFBOARDS]See SolveBoard +int solutions[MAXNOOFBOARDS]See SolveBoard -int mode[MAXNOOFBOARDS]See SolveBoard +int mode[MAXNOOFBOARDS]See SolveBoard @@ -533,13 +543,13 @@ Common encodings are as follows int cardsNumber of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7. -int suit[13]Suit of the each returned card. Suit encoding. +int suit[13]Suit of the each returned card. Suit encoding. int rank[13]Rank of the returned card. Value range 2-14. -int equals[13]Lower-ranked equals. Holding encoding. +int equals[13]Lower-ranked equals. Holding encoding. int score[13]-1: target not reached. Otherwise: Target of maximum number of tricks. @@ -565,7 +575,7 @@ Common encodings are as follows StructFieldComment -ddTableResultsint resTable[5][4]Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. +ddTableResultsint resTable[5][4]Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. @@ -588,10 +598,10 @@ Common encodings are as follows StructFieldComment -parResultschar parScore[2][16]First index is NS/EW. Side encoding. +parResultschar parScore[2][16]First index is NS/EW. Side encoding. -char parContractsString[2][128]First index is NS/EW. Side encoding. +char parContractsString[2][128]First index is NS/EW. Side encoding. @@ -681,7 +691,7 @@ Common encodings are as follows playTraceBinint numberNumber of cards in the play trace, starting from the beginning of the hand. -int suit[52]Suit encoding. +int suit[52]Suit encoding. int rank[52]Encoding 2 .. 14 (not Card encoding). @@ -796,7 +806,7 @@ There is a “transposition table” memory associated with each th The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. -For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). +For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). @@ -913,9 +923,9 @@ 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. -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. +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. +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: @@ -973,7 +983,7 @@ It is important to understand the parallelism and the concept of a chunk. If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. @@ -1046,15 +1056,15 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or
-The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. +The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to [CalcDDtable](#CalcDDtable). Since the input is a table, there is no PBN and non-PBN version of these functions. Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. -The `vulnerable` parameter is given using Vulnerable encoding. +The `vulnerable` parameter is given using [Vulnerable](#Vulnerable) encoding. 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. -The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. +The DealerPar() function also uses knowledge of the `dealer` using [Hand](#Hand) encoding. The rgument 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. The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). @@ -1075,7 +1085,7 @@ DealerPar() and SidesPar() give each par contract as a separate text string: * “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. * SidesPar() give the par contract text strings as described above for each side. -DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. +DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the [`parResultsMaster`](#parResultsMaster) structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. Output example from ConvertToDealerTextFormat: @@ -1140,7 +1150,7 @@ Both functions are deprecated. Instead use one of the CalcDDtable functions foll AnalysePlayPBN is just like AnalysePlayBin, except for the input format. -The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. +The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses [SolveBoard](#SolveBoard), the same comments apply concerning the thread number `thrId` and the transposition tables. As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: @@ -1174,7 +1184,7 @@ AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. The AnalyseAllPlays\* 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. -Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. +Concerning chunkSize, exactly the 21 same remarks apply as with [SolveAllChunksBin](#SolveAllChunksBin). From dad4665f6fd881769a22394d4a967705934a35ad Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 23 Dec 2014 03:07:51 +0100 Subject: [PATCH 109/199] Corrections after review --- doc/dll-description.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 4a4096ff..49e08651 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -334,6 +334,13 @@ of the dealer. + + + + + +
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
ErrorMessageint codeTurns a return code into an error message string.
char line[80] +
@@ -821,7 +828,7 @@ play.
Return only one of the optimum cards and its score. -12Find the maximum number of tricks for the side to -play.Return all optimum cards and their scores. +play.
Return all optimum cards and their scores. 01Return only one of the cards legal to play, with @@ -883,7 +890,7 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure -struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBNddTableDealPBN"> +struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN struct ddTableResults *tablepstruct ddTableResults *tablep @@ -912,7 +919,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy struct ddTablesRes *respstruct ddTablesRes *resp -ddTablesRes"> + <struct allParResults *prespstruct allParResults *presp @@ -957,7 +964,7 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + @@ -1088,14 +1095,13 @@ DealerPar() and SidesPar() give each par contract as a separate text string: DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the [`parResultsMaster`](#parResultsMaster) structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. -Output example from ConvertToDealerTextFormat: +Output example from ConvertToDealerTextFormat: “Par 110: NS 2S NS 2H” -Output examples from ConvertToSidesTextFormat: - -“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT
+Output examples from ConvertToSidesTextFormat: +“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. +”NS Par -120: W 2NT EW Par 120: W 1NT+1” when it matters who starts the bidding.
SolveAllBoardsSolveAllChunksBinSolveAllChunksPBNSolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
From 450358a871933518c58d1f8e666dcf8f67fef1ae Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 23 Dec 2014 10:14:17 +0100 Subject: [PATCH 110/199] Lots of closing-tag errors --- doc/dll-description.md | 124 ++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 71 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 49e08651..71e12028 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -2,7 +2,7 @@ Bo Haglund, Soren Hein, Bob Richardson Rev X, 2014-11-16 -Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ +Latest DLL issue with this description is available at [http://www.bahnhof.se/wb758135/](http://www.bahnhof.se/wb758135/) # Description of the DLL functions supported in Double Dummy Problem Solver 2.8 ## Callable functions @@ -18,7 +18,7 @@ The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand a ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. +The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand's trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. @@ -34,8 +34,8 @@ The PAR calculation functions find the optimal contract(s) assuming open cards a Two alternatives are given: -1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. -2. The dealer hand is assumed to “start the bidding”. +1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. +2. The dealer hand is assumed to “start the bidding”. The presentation of the par score and contracts are given in alternative formats. @@ -142,14 +142,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -259,7 +259,7 @@ of the dealer. - + @@ -302,7 +302,7 @@ of the dealer. - + @@ -341,6 +341,7 @@ of the dealer. +
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don't use!
struct solvedBoards *solvedp struct ddTabeleResults *tablep
struct parResults *prespstruct parResults *presp
 
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plp
char line[80]
@@ -396,7 +397,7 @@ Common encodings are as follows Bit 14Rank of ace   -HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero. +HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.   PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K @@ -451,7 +452,6 @@ Common encodings are as follows - structFieldComment @@ -461,7 +461,6 @@ Common encodings are as follows - structFieldComment @@ -471,11 +470,10 @@ Common encodings are as follows - structFieldComment -ddTableDealsint noOfTablesNumber of DD table deals in structure, at most MAXNOOFTABLES +ddTableDealsint noOfTablesNumber of DD table deals in structure, at most MAXNOOFTABLES struct ddTableDeal deals[X]X = MAXNOOFTABLES * DDS_STRAINS @@ -484,11 +482,10 @@ Common encodings are as follows - structFieldComment -ddTableDealsPBNint noOfTablesNumber of DD table deals in structure +ddTableDealsPBNint noOfTablesNumber of DD table deals in structure struct ddTableDealPBN deals[X]X = MAXNOOFTABLES * DDS_STRAINS @@ -497,7 +494,6 @@ Common encodings are as follows - structFieldComment @@ -519,11 +515,10 @@ Common encodings are as follows - structFieldComment -boardsPBNint noOfBoardsNumber of boards +boardsPBNint noOfBoardsNumber of boards struct dealPBN[MAXNOOFBOARDS] @@ -544,10 +539,10 @@ Common encodings are as follows structFieldComment -futureTricksint nodesNumber of nodes searched by the DD solver. +futureTricksint nodesNumber of nodes searched by the DD solver. -int cardsNumber of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7. +int cardsNumber of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7. int suit[13]Suit of the each returned card. Suit encoding. @@ -565,11 +560,10 @@ Common encodings are as follows - structFieldComment -solvedBoardsint noOfBoards +solvedBoardsint noOfBoards struct futureTricks solvedBoard [MAXNOOFBOARDS] @@ -578,7 +572,6 @@ Common encodings are as follows - StructFieldComment @@ -588,7 +581,6 @@ Common encodings are as follows - structFieldComment @@ -601,20 +593,18 @@ Common encodings are as follows - StructFieldComment parResultschar parScore[2][16]First index is NS/EW. Side encoding. -char parContractsString[2][128]First index is NS/EW. Side encoding. +char parContractsString[2][128]First index is NS/EW. Side encoding. - StructFieldComment @@ -624,7 +614,6 @@ Common encodings are as follows - StructFieldComment @@ -640,7 +629,6 @@ Common encodings are as follows - StructFieldComment @@ -656,7 +644,6 @@ Common encodings are as follows - StructFieldComment @@ -678,7 +665,6 @@ Common encodings are as follows - StructFieldComment @@ -691,7 +677,6 @@ Common encodings are as follows - StructFieldComment @@ -707,7 +692,6 @@ Common encodings are as follows - StructFieldComment @@ -720,7 +704,6 @@ Common encodings are as follows - StructFieldComment @@ -733,7 +716,6 @@ Common encodings are as follows - StructFieldComment @@ -746,20 +728,18 @@ Common encodings are as follows - StructFieldComment solvedPlayint number -int tricks[53];Starting position and up to 52 cards +int tricks[53]Starting position and up to 52 cards - StructFieldComment @@ -801,19 +781,19 @@ Common encodings are as follows -SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. +SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don't do that, and they also hide the implementation details such as transposition tables, see below. -SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. +SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. -SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. +SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. -There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. +There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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't be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. -The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. +The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. -For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). +For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). @@ -857,7 +837,7 @@ If the target cannot be achieved, only one card is returned with the score set a - + @@ -871,7 +851,7 @@ If the target cannot be achieved, only one card is returned with the score set a Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, and we may use it for something else in the future. If you think you need it, let us know! -“Reuse” means “reuse the transposition table from the previous run with the same thread number”. +“Reuse” means “reuse the transposition table from the previous run with the same thread number”. For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. 1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` @@ -899,7 +879,7 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don't always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “\*tablep” , which must be declared before calling CalcDDtable. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “\*tablep” , which must be declared before calling CalcDDtable. @@ -928,11 +908,11 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy 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. +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. -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. +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. +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: @@ -980,7 +960,7 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
-`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. +`SolveAllChunks` is an alias for SolveAllChunksPBN; don't use it. `SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. @@ -1019,7 +999,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or   -SidesPar  +SidesPar  struct ddTableResults *tablep  @@ -1034,7 +1014,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or   -DealerParBinSidesParBin +DealerParBinSidesParBin struct ddTableResults *tablepstruct ddTableResults *tablep @@ -1065,7 +1045,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to [CalcDDtable](#CalcDDtable). Since the input is a table, there is no PBN and non-PBN version of these functions. -Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. +Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. The `vulnerable` parameter is given using [Vulnerable](#Vulnerable) encoding. @@ -1075,21 +1055,21 @@ The DealerPar() function also uses knowledge of the `dealer` using [Hand](#Hand) The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). -In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. +In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. -* “NS:NS 23S,N 23H”: Only North makes 3 hearts. -* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,N 23H”: Only North makes 3 hearts. +* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. DealerPar() and SidesPar() give each par contract as a separate text string: -* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. -* “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. +* “3N-EW” means that E and W can both make exactly 3NT. +* “4N-W+1” 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'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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. * SidesPar() give the par contract text strings as described above for each side. DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the [`parResultsMaster`](#parResultsMaster) structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. @@ -1097,12 +1077,12 @@ DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. Output example from ConvertToDealerTextFormat: -“Par 110: NS 2S NS 2H” +“Par 110: NS 2S NS 2H” Output examples from ConvertToSidesTextFormat: -“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT -EW Par 120: W 1NT+1” when it matters who starts the bidding. +“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. +”NS Par -120: W 2NT +EW Par 120: W 1NT+1” when it matters who starts the bidding. @@ -1158,11 +1138,11 @@ AnalysePlayPBN is just like AnalysePlayBin, except for the input format. The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses [SolveBoard](#SolveBoard), the same comments apply concerning the thread number `thrId` and the transposition tables. -As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: +As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer's play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: 9 10 10 10 10 9 9 -The number of tricks are always seen from declarer’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. +The number of tricks are always seen from declarer'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.
@@ -1195,7 +1175,7 @@ Concerning chunkSize, exactly the 21 same remarks apply as with [SolveAllChunksB
- + @@ -1285,6 +1265,7 @@ different number of boards in its first two arguments. + @@ -1326,7 +1307,7 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + @@ -1393,5 +1374,6 @@ ConvertToDealerTextFormat, ConvertToSidesTextFormat + -
SetMaxThreadsFreeMemorySetMaxThreadsFreeMemory
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.Rev B2006‑03‑20Updated issue
Rev C2006‑03‑28Updated issue. Addition of the SolveBoard parameter ”mode”Rev C2006‑03‑28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006‑04‑05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev X2014‑11‑16Extended maximum number of tables when calling CalcAllTables.
+ \ No newline at end of file From ebafc9e08aed0098305612d3ed424429b166b596 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 08:48:21 +0100 Subject: [PATCH 111/199] First part of converting dds DOC to md --- doc/dll-description.md | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 doc/dll-description.md diff --git a/doc/dll-description.md b/doc/dll-description.md new file mode 100644 index 00000000..a8414f41 --- /dev/null +++ b/doc/dll-description.md @@ -0,0 +1,49 @@ +Bo Haglund, Bob Richardson +Rev V, 2014-10-14 +Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ + +# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +## Callable functions +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +Return codes are given at the end. + +Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! + +## The Basic Functions + +The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. + +### The Multi-Thread Double Dummy Solver Functions + +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. + +To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. + +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. + +The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. + +The call `FreeMemory` causes DDS to give up its dynamically allocated memory. + +### The PAR Calculation Functions + +The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. + +Two alternatives are given: + +1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. +2. The dealer hand is assumed to “start the bidding”. + +The presentation of the par score and contracts are given in alternative formats. + +The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. + +The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. + +It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. + +The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. + +### Double Dummy Value Analyser Functions + +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file From d851e73a89087364cba1ddc6689bb142897110c9 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:09:33 +0100 Subject: [PATCH 112/199] First try at the big table in dss.md --- doc/dll-description.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index a8414f41..d6d7b6c7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -1,5 +1,7 @@ Bo Haglund, Bob Richardson + Rev V, 2014-10-14 + Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ # Description of the DLL functions supported in Double Dummy Problem Solver 2.7 @@ -46,4 +48,11 @@ The par calculation is executed using a single thread. But the calculation is ve ### Double Dummy Value Analyser Functions -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. + +------------------------------------------------------------------- +Function | Arguments | Format | Comment +------------------------------------------------------------------- +| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | +| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | + From 7495b51b49b2c20484463c4714a1648f977ee9e8 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:16:58 +0100 Subject: [PATCH 113/199] Second try at the big table in dss.md --- doc/dll-description.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index d6d7b6c7..7121c37d 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -51,8 +51,19 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. ------------------------------------------------------------------- -Function | Arguments | Format | Comment +Function | Arguments | Format | Comment | ------------------------------------------------------------------- -| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | -| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | Binary | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +------------------------------------------------------------------------ From bbc5d5b1ef0ee246fdbf2b4d3b75b06963f28984 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:22:25 +0100 Subject: [PATCH 114/199] Third try at the big table in dss.md --- doc/dll-description.md | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 7121c37d..34bcd527 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,20 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -------------------------------------------------------------------- -Function | Arguments | Format | Comment | -------------------------------------------------------------------- -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | Binary | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | ------------------------------------------------------------------------- +| Function | Arguments | Format | Comment | +------------------|---------------------------|--------|---------------------------| +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | From 81ac464ab2a06badf7b5e83bba22500493e95ad7 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:37:48 +0100 Subject: [PATCH 115/199] Next try at the big table in dss.md, now with embedded HTL table --- doc/dll-description.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 34bcd527..5af61ad7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,18 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -| Function | Arguments | Format | Comment | -------------------|---------------------------|--------|---------------------------| -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | - + + + + + + + + + + + + + + +
FunctionArgumentsFormatComment
`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play
`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format.
\ No newline at end of file From 68b1d768ab8f4bf57ba2a66b302b27371998e041 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:55:36 +0100 Subject: [PATCH 116/199] Still experimenting with HTML in mrkdown --- doc/dll-description.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 5af61ad7..54ef1a86 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,10 +58,10 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format. +`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. \ No newline at end of file From d0dab52a17e2e9f589a3abcc309259bfd43097ff Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:59:54 +0100 Subject: [PATCH 117/199] That was ugly. Next try --- doc/dll-description.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 54ef1a86..434dd758 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,10 +58,42 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + +int threadIndex + + +`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. + + +int target + + +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + + +int threadIndex \ No newline at end of file From 8d2f2e8f3621f8b650a26ab1128cf386c6b3f6d2 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:01:25 +0100 Subject: [PATCH 118/199] That was ugly. Next try --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 434dd758..105602d7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,7 +58,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play int target From 2914ecb91269b0b55b936c4b81f34f366b986dd1 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:02:23 +0100 Subject: [PATCH 119/199] Much better now --- doc/dll-description.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 105602d7..11033a54 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -81,9 +81,6 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int target -int target - - int solutions From f6bc7aa649b6c0843bc2878df0225dff5bbb1127 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:27:49 +0100 Subject: [PATCH 120/199] Working examples --- doc/dll-description.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/dll-description.md b/doc/dll-description.md index 11033a54..23fac1dc 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,6 +50,7 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. + @@ -75,6 +76,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal + From de538b5e6c90e21b9200aaa87d60b4febf39b55d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:29:32 +0100 Subject: [PATCH 121/199] Working on dds.md --- doc/dll-description.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 23fac1dc..884887d7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -77,7 +77,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + From b59e1dfa1a4eb5461d14d5e1e4f93a9821456ed4 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 07:22:00 +0100 Subject: [PATCH 122/199] Added .gitignore --- doc/dll-description.md | 85 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 884887d7..f3ec539a 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -75,8 +75,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -94,5 +94,88 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +tr> + + + + + + + + +
int threadIndex
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later playSolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int threadIndex
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format.
struct solvedBoards *solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
\ No newline at end of file From 26244937c4f4448b2e19f57501f4e718aed2c1c7 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Thu, 20 Nov 2014 08:18:29 +0100 Subject: [PATCH 123/199] All functiond described in dds.md --- doc/dll-description.md | 164 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 4 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index f3ec539a..a0d82343 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -149,7 +149,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! struct solvedBoards *solvedp @@ -169,7 +169,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal tr>  -SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -177,5 +177,161 @@ tr>  int chunkSize +  + +Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. + + +struct parResults *presp + + +int vulnerable + +  + +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. + + +struct parResultsDealer *presp + + +int dealer + + +int vulnerable + +  + +DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. + + +struct parResultsMaster * presp + + +int dealer + + +int vulnerable + +  + +ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. + + +char *resp + +  + +SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. + + +struct parResultsDealer *presp + + +int vulnerable + +  + +SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. + + +struct parResultsMaster sidesRes[2] + + +int vulnerable + +  + +ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. + + +char *resp + +  + +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! + + +int vulnerable + + +struct ddTableResults *tablep + + +struct parResults *presp + +  + +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! + + +struct ddTableResults *tablep + + +int vulnerable + + +struct parResults *presp + +  + +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. + + +struct playTraceBin play + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. + + +struct playTracePBN playPBN + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. + + +struct playTracesBin *plp + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. + + +struct playTracesPBN *plpPBN + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. + +  + +FreeMemoryvoidPBNFrees DDS allocated dynamical memory. + - \ No newline at end of file + From 1b5c156e64bc751c548aa9609d027c2db3c849b0 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:46:58 +0100 Subject: [PATCH 124/199] Finished tables in dds.md --- doc/dll-description.md | 460 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) diff --git a/doc/dll-description.md b/doc/dll-description.md index a0d82343..7283e59e 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -335,3 +335,463 @@ tr>  +### Data sructure +Common encodings are as follows + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
+ + + + + + + + + + + +
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding PBN encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
+ + + + + + + + + + + +
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
+ + + + + + + + + + + +
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
+ + + + + + + + + + + + + + +
structFieldComment
parTextResultschar parText[2][128];
int equal;
+ + + + + + + + + + + + + + + + + +
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
+ + + + + + + + + + + + + + +
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
+ + + + + + + + + + + + + + +
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlayint number;
int tricks[53];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS / 10];
\ No newline at end of file From 847c6e5fc3f602f7bc4f1ad50cb9288cf924032c Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:59:06 +0100 Subject: [PATCH 125/199] Finished tables in dds.md --- doc/dll-description.md | 218 ++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 132 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 7283e59e..14cb1eae 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -415,15 +415,12 @@ Common encodings are as follows unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. - - - - + + + - - @@ -439,57 +436,49 @@ Common encodings are as follows - -
structFieldComment
dealPBNint trump;Suit encoding
char remainCards[80];Remaining cards. PBN encoding.
- - + + + + - - - -
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
- - + + + + - - @@ -505,15 +494,13 @@ Common encodings are as follows - -
structFieldComment
boardsint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + + - - @@ -529,15 +516,12 @@ Common encodings are as follows - -
structFieldComment
boardsPBNint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + - - @@ -556,84 +540,72 @@ Common encodings are as follows - -
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
- - + + + + - - - -
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
- - + + + + - - - -
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
- - + + + + - - - -
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
- - + + + + - - - -
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
- - + + + + - - @@ -643,15 +615,13 @@ Common encodings are as follows - -
structFieldComment
parResultsDealerint number;
char contracts[10][10];
- - + + + + - - @@ -661,15 +631,13 @@ Common encodings are as follows - -
structFieldComment
parResultsMasterint score;
struct contractType contracts[10];
- - + + + + - - @@ -685,30 +653,26 @@ Common encodings are as follows - -
structFieldComment
contractTypeint underTricks;
int seats;
- - + + + + - - - -
structFieldComment
parTextResultschar parText[2][128];
int equal;
- - + + + + - - @@ -718,75 +682,65 @@ Common encodings are as follows - -
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int rank[52];Encoding 2 .. 14 (not Card encoding).
- - + + + + - - - -
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
- - + + + + - - - -
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
solvedPlayint number;
int tricks[53];
- - + + + + - - From e0057e34e63ede307c002287247c2f0d2a7749de Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 01:40:49 +0100 Subject: [PATCH 126/199] Added a few pages --- doc/dll-description.md | 103 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 14cb1eae..a890c51c 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -748,4 +748,105 @@ Common encodings are as follows -
structFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS / 10];
\ No newline at end of file + + +### Functions + + + + + + + + + + + + + + + + + + + + + + + + + + +
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,
int threadIndexint threadIndex
+SolveBoardPBN is just like SolveBoard, except for the input format. + +SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. + +SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. + +There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. + +The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. + +For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
targetsolutionscomment
-11Find the maximum number of tricks for the side to +play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to +play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with +score set to 0.
02Return all cards that legal to play, with score set to +0.
1 .. 131If score is -1: Target cannot be reached.
+If score is 0: In fact no tricks at all can be won.
+If score is > 0: score will always equal target, even if more tricks can be won.
+One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
+If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
+“Reuse” means “reuse the transposition table from the previous run with the same thread number”. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. + +1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + From e324452884928cced1a97afda65fcc4729133e92 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 04:48:51 +0100 Subject: [PATCH 127/199] All text typed. --- doc/dll-description.md | 471 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 466 insertions(+), 5 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index a890c51c..c4887f0c 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -167,7 +167,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int chunkSize -tr>  +  SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. @@ -845,8 +845,469 @@ If the target cannot be achieved, only one card is returned with the score set a “Reuse” means “reuse the transposition table from the previous run with the same thread number”. For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. -1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` -2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` +1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` + +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` + +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + + + + + + + + + + + + + + + +
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults * tablepstruct ddTableResults * tablep
+CalcDDtablePBN is just like CalcDDtable, except for the input format. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. + + + + + + + + + + + + + + + + + + + + + + + + +
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *resp
struct allParResults *prespstruct allParResults *presp
+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. +The “mode” parameter contains the vulnerability (Vulnerable encoding) 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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + + + + + + + + + + + + + + + + + + + + + + + + +
Number of strainsMaximum number of DD tables
510
412
316
225
150
+ + + + + + + + + + + + + + + + + + +
SolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
+`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. +`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; +don’t use it. +The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +It is important to understand the parallelism and the concept of a chunk. +If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused +within a chunk. +No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: +* The same board is played at two tables of a team match. +* A board is played at 10 tables in a pairs tournament. +* The trump suit is the same, and there are very minor differences in the rest. +The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. +Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParDealerPar
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults *tablep 
struct parResultsDealer *sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster * prespstruct parResultsMaster * presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster *presstruct parResultsMaster *pres
char *respstruct parTextResults *resp
+The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. + +Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. + +The `vulnerable` parameter is given using Vulnerable encoding. + +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. + +The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. + +The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). + +In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. + +There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. + +Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: + +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,N 23H”: Only North makes 3 hearts. +* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. + +DealerPar() and SidesPar() give each par contract as a separate text string: + +* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. +* “3N-EW” means that E and W can both make exactly 3NT. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* SidesPar() give the par contract text strings as described above for each side. + +DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. + +After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. +Output example from ConvertToDealerTextFormat: + +“Par 110: NS 2S NS 2H” + +Output examples from ConvertToSidesTextFormat: + +“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. +”NS Par -120: W 2NT +EW Par 120: W 1NT+1” when it matters who starts the bidding. + + + + + + + + + + + + + + + + + + + + + +
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
+ +AnalysePlayPBN is just like AnalysePlayBin, except for the input format. + +The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. + +As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: + +9 10 10 10 10 9 9 + +The number of tricks are always seen from declarer’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. + + + + + + + + + + + + + + + + + + + + + +
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards *bopstruct boardsPBN *bopPBN
struct playTracesBin *plpstruct playTracesPBN *plpPBN
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
+AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. + +The AnalyseAllPlays* 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. + +Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. + + + + + + + + + + + + +
SetMaxThreadsFreeMemory
int userThreadsvoid
+SetMaxThreads returns the actual number of threads. + +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 threads 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. + +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. + +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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. + +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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. + +=== Return codes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a +different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. +Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +ConvertToDealerTextFormat, ConvertToSidesTextFormat
From 53a8d8fa699555c2a78011c7e155a378745a19ca Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 05:55:42 +0100 Subject: [PATCH 128/199] All changes made from diff. Document is now on par with v 2.8.0 --- doc/dll-description.md | 153 +++++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 59 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index c4887f0c..97a95458 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -1,31 +1,32 @@ -Bo Haglund, Bob Richardson +Bo Haglund, Soren Hein, Bob Richardson -Rev V, 2014-10-14 +Rev X, 2014-11-16 Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ -# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 ## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. + Return codes are given at the end. Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! ## The Basic Functions -The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. +The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. -The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. +The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. -The call `FreeMemory` causes DDS to give up its dynamically allocated memory. +Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. ### The PAR Calculation Functions @@ -142,7 +143,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format. +SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! struct solvedBoards *solvedp @@ -189,7 +190,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +of the dealer. struct parResultsDealer *presp @@ -327,12 +329,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) + +  + +FreeMemoryvoid Frees DDS allocated dynamical memory.   -FreeMemoryvoidPBNFrees DDS allocated dynamical memory. +ErrorMessageint code Turns a return code into an error message string. + + ### Data sructure @@ -413,7 +421,7 @@ Common encodings are as follows int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. +unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. @@ -454,10 +462,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTables;Number of DD table deals in structure +ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableDeal deals[MAXNOOFBOARDS/4]; +struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINS @@ -535,7 +543,7 @@ Common encodings are as follows int rank[13];Rank of the returned card. Value range 2-14. -int equals[13];Lower-ranked equals. Holding PBN encoding. +int equals[13];Lower-ranked equals. Holding encoding. int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks. @@ -558,7 +566,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. @@ -571,17 +579,17 @@ Common encodings are as follows structFieldComment -ddTablesResint noOfBoards; +ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableResults results[MAXNOOFBOARDS/4]; +struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINS -structFieldComment +StructFieldComment parResultschar parScore[2][16];First index is NS/EW. Side encoding. @@ -594,17 +602,17 @@ Common encodings are as follows -structFieldComment +StructFieldComment -allParResultsstruct parResults[MAXNOOFBOARDS/20]; +allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table -structFieldComment +StructFieldComment parResultsDealerint number; @@ -620,7 +628,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parResultsMasterint score; @@ -636,7 +644,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment contractTypeint underTricks; @@ -658,7 +666,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parTextResultschar parText[2][128]; @@ -671,7 +679,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -687,7 +695,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -700,7 +708,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesBinint noOfBoards; @@ -713,7 +721,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesPBNint noOfBoards; @@ -726,26 +734,26 @@ Common encodings are as follows -structFieldComment +StructFieldComment solvedPlayint number; -int tricks[53]; +int tricks[53];Starting position and up to 52 cards -structFieldComment +StructFieldComment solvedPlaysint noOfBoards; -struct solvedPlay solved[MAXNOOFBOARDS / 10]; +struct solvedPlay solved[MAXNOOFBOARDS]; @@ -778,10 +786,12 @@ Common encodings are as follows -SolveBoardPBN is just like SolveBoard, except for the input format. +SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. + SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. @@ -842,8 +852,11 @@ If the target cannot be achieved, only one card is returned with the score set a +Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, +and we may use it for something else in the future. If you think you need it, let us know! + “Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. 1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` @@ -896,10 +909,14 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy 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. -The “mode” parameter contains the vulnerability (Vulnerable encoding) for use in the par calculation. It is set to -1 if no par calculation is to be performed. + +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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + +The maximum number of DD tables in a CallAllTables call depends on the number of strains required, see the following table: @@ -909,19 +926,19 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + - + - +
510532
412440
316353
225280
1501160
@@ -929,15 +946,15 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + @@ -945,19 +962,20 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
SolverAllChunksBinSolveAllChunksPBNSolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bopstruct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. -`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; -don’t use it. + +`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. + The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. + It is important to understand the parallelism and the concept of a chunk. + If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused -within a chunk. -No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: -* The same board is played at two tables of a team match. -* A board is played at 10 tables in a pairs tournament. -* The trump suit is the same, and there are very minor differences in the rest. -The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. -Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. + +No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. + +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! @@ -1065,7 +1083,7 @@ Output example from ConvertToDealerTextFormat: Output examples from ConvertToSidesTextFormat: “NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT +”NS Par -120: W 2NT
EW Par 120: W 1NT+1” when it matters who starts the bidding.
@@ -1150,7 +1168,11 @@ DDS then checks whether a number of threads equal to the number of cores will fi 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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. +It may be possible, 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. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. + +It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. === Return codes
@@ -1204,6 +1226,17 @@ different number of boards in its first two arguments. + + + + + + + + + + + @@ -1309,5 +1342,7 @@ AnalyseAllPlaysPBN + +
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From a0831c5b42730d7f7c2c95b1f09ec94f656baf64 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 07:56:46 +0100 Subject: [PATCH 129/199] Changes made focussing on Markup syntax --- doc/dll-description.md | 172 ++++++++++++++++++++++------------------- 1 file changed, 91 insertions(+), 81 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 97a95458..32bef118 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -18,7 +18,7 @@ The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand a ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. +The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. @@ -51,7 +51,6 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - @@ -72,7 +71,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -90,7 +89,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -100,18 +99,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -120,14 +119,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -136,65 +135,65 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - - + @@ -204,10 +203,10 @@ of the dealer. - + - + @@ -217,24 +216,24 @@ of the dealer. - + - + - + - + - + @@ -244,10 +243,10 @@ of the dealer. - + - + @@ -257,23 +256,23 @@ of the dealer. - + - + - + - + @@ -283,7 +282,7 @@ of the dealer. - + @@ -296,33 +295,33 @@ of the dealer. - + - + - + - + - + - + - + @@ -343,8 +342,10 @@ of the dealer.
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndex
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndexCalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded.SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *prespstruct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int dealer
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster * prespstruct parResultsMaster \* presp
int dealer
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char *respchar \*resp
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char *respchar \*resp
 
int vulnerable
struct ddTableResults *tablepstruct ddTableResults \*tablep
struct parResults *prespstruct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablepstruct ddTableResults \*tablep
int vulnerable
struct parResults *prespstruct parResults \*presp
 
struct playTraceBin play
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId struct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plpstruct playTracesBin \*plp
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBNstruct playTracesPBN \*plpPBN
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
-### Data sructure + +## Data structure Common encodings are as follows + @@ -465,7 +466,7 @@ Common encodings are as follows - + @@ -582,7 +583,7 @@ Common encodings are as follows - + @@ -758,7 +759,8 @@ Common encodings are as follows
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
-### Functions +## Functions + @@ -779,16 +781,17 @@ Common encodings are as follows - +
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
+ SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. -SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. @@ -852,6 +855,7 @@ If the target cannot be achieved, only one card is returned with the score set a + Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, and we may use it for something else in the future. If you think you need it, let us know! @@ -877,12 +881,13 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN -struct ddTableResults * tablepstruct ddTableResults * tablep +struct ddTableResults \* tablepstruct ddTableResults \* tablep + CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. @@ -892,7 +897,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + @@ -901,16 +906,17 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + - +
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealspstruct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint modeint trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *respstruct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults *prespstruct allParResults *prespstruct allParResults \*prespstruct allParResults \*presp
+ 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. +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. 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. @@ -951,21 +957,22 @@ The maximum number of DD tables in a CallAllTables call depends on the number of -struct boards *bopstruct boards *bopstruct boardsPBN *bop +struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop -struct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp +struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp int chunkSizeint chunkSize + `SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. `SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. -The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. It is important to understand the parallelism and the concept of a chunk. @@ -985,10 +992,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResults *prespstruct parResultsDealer *presp +struct parResults \*prespstruct parResultsDealer \*presp int vulnerableint dealer @@ -1003,10 +1010,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or Sidespar  -struct ddTableResults *tablep  +struct ddTableResults \*tablep  -struct parResultsDealer *sidesRes[2]  +struct parResultsDealer \*sidesRes[2]  int vulnerable  @@ -1018,10 +1025,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or DealerParBinSidesParBin -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResultsMaster * prespstruct parResultsMaster * presp +struct parResultsMaster \* prespstruct parResultsMaster \* presp int vulnerableint dealer @@ -1036,13 +1043,14 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or ConvertToDealerTextForamatConvertToSidesTextFormat -struct parResultsMaster *presstruct parResultsMaster *pres +struct parResultsMaster \*presstruct parResultsMaster \*pres -char *respstruct parTextResults *resp +char \*respstruct parTextResults \*resp + The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. @@ -1061,8 +1069,7 @@ There may be several par contracts, for instance 3NT just making and 5C just mak Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. * “NS:NS 23S,N 23H”: Only North makes 3 hearts. * “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. @@ -1070,7 +1077,7 @@ DealerPar() and SidesPar() give each par contract as a separate text string: * “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. * “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. * SidesPar() give the par contract text strings as described above for each side. DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. @@ -1100,7 +1107,7 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding. struct playTraceBin playstruct playTracePBN playPBN -struct solvedPlay *solvedpstruct solvedPlay *solvedp +struct solvedPlay \*solvedpstruct solvedPlay \*solvedp int thrIdint thrId @@ -1126,22 +1133,23 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one -struct boards *bopstruct boardsPBN *bopPBN +struct boards \*bopstruct boardsPBN \*bopPBN -struct playTracesBin *plpstruct playTracesPBN *plpPBN +struct playTracesBin \*plpstruct playTracesPBN \*plpPBN -struct solvedPlays *solvedpstruct solvedPlays *solvedp +struct solvedPlays \*solvedpstruct solvedPlays \*solvedp int chunkSizeint chunkSize + AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. -The AnalyseAllPlays* 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. +The AnalyseAllPlays\* 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. Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. @@ -1157,6 +1165,7 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi + SetMaxThreads returns the actual number of threads. 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 threads than there are processor cores, as this will only require more memory and will not improve performance. Within these constraints, DDS auto-configures the @@ -1174,7 +1183,8 @@ SetMaxThreads can be called multiple times even within the same session. So it i It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. -=== Return codes +## Return codes + @@ -1237,7 +1247,7 @@ different number of boards in its first two arguments. - @@ -1252,13 +1262,13 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + - + - +
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
From 17fc5a7df888e4b260b85abb9155bc9de43d32e2 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 21:21:16 +0100 Subject: [PATCH 130/199] Extra commit before copying the file --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 32bef118..452d2ca3 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -22,7 +22,7 @@ The double dummy trick values for all 5 \* 4 = 20 possible combinations of a han To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. From 05383cd72554a3dba0b23feff57b3911519bd6be Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 21:40:35 +0100 Subject: [PATCH 131/199] trying to get rid of dds.md --- dds.md | 1358 -------------------------------------------------------- 1 file changed, 1358 deletions(-) delete mode 100644 dds.md diff --git a/dds.md b/dds.md deleted file mode 100644 index 452d2ca3..00000000 --- a/dds.md +++ /dev/null @@ -1,1358 +0,0 @@ -Bo Haglund, Soren Hein, Bob Richardson - -Rev X, 2014-11-16 - -Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ - -# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 -## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. - -Return codes are given at the end. - -Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! - -## The Basic Functions - -The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. - -### The Multi-Thread Double Dummy Solver Functions - -The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. - -To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. - -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. - -The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. - -Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. - -### The PAR Calculation Functions - -The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. - -Two alternatives are given: - -1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. -2. The dealer hand is assumed to “start the bidding”. - -The presentation of the par score and contracts are given in alternative formats. - -The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. - -The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. - -It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. - -The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. - -### Double Dummy Value Analyser Functions - -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionArgumentsFormatComment
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge -of the dealer.
struct parResultsDealer \*presp
int dealer
int vulnerable
 
DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster \* presp
int dealer
int vulnerable
 
ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char \*resp
 
SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
int vulnerable
 
ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char \*resp
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTableResults \*tablep
struct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults \*tablep
int vulnerable
struct parResults \*presp
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
struct solvedPlay \*solvedp
int thrId
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
struct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin \*plp
struct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN \*plpPBN
struct solvedPlays \*solvedp
int chunkSize
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
ErrorMessageint code Turns a return code into an error message string.
-
- -## Data structure -Common encodings are as follows - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
StructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
StructFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
StructFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
StructFieldComment
parTextResultschar parText[2][128];
int equal;
StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
StructFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
StructFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
StructFieldComment
solvedPlayint number;
int tricks[53];Starting position and up to 52 cards
StructFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- -## Functions - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
- -SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. - -SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. - -If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. - -SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. - -There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. - -The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. - -For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
targetsolutionscomment
-11Find the maximum number of tricks for the side to -play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to -play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with -score set to 0.
02Return all cards that legal to play, with score set to -0.
1 .. 131If score is -1: Target cannot be reached.
-If score is 0: In fact no tricks at all can be won.
-If score is > 0: score will always equal target, even if more tricks can be won.
-One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
-If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
- -Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, -and we may use it for something else in the future. If you think you need it, let us know! - -“Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. - -1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` - -2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` - -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` - -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` - - - - - - - - - - - - - - - -
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablep
- -CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. - - - - - - - - - - - - - - - - - - - - - - - - -
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults \*prespstruct allParResults \*presp
- -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. - -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: - - - - - - - - - - - - - - - - - - - - - - - - -
Number of strainsMaximum number of DD tables
532
440
353
280
1160
- - - - - - - - - - - - - - - - - - -
SolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp
int chunkSizeint chunkSize
- -`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. - -`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. - -The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. - -It is important to understand the parallelism and the concept of a chunk. - -If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. - -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. - -No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. - -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! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResults \*prespstruct parResultsDealer \*presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults \*tablep 
struct parResultsDealer \*sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResultsMaster \* prespstruct parResultsMaster \* presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
char \*respstruct parTextResults \*resp
- -The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. - -Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. - -The `vulnerable` parameter is given using Vulnerable encoding. - -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. - -The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. - -The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). - -In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. - -There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. - -Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: - -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. -* “NS:NS 23S,N 23H”: Only North makes 3 hearts. -* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. - -DealerPar() and SidesPar() give each par contract as a separate text string: - -* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. -* “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. -* SidesPar() give the par contract text strings as described above for each side. - -DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. - -After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. -Output example from ConvertToDealerTextFormat: - -“Par 110: NS 2S NS 2H” - -Output examples from ConvertToSidesTextFormat: - -“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT
-EW Par 120: W 1NT+1” when it matters who starts the bidding. - - - - - - - - - - - - - - - - - - - - - -
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedp
int thrIdint thrId
- -AnalysePlayPBN is just like AnalysePlayBin, except for the input format. - -The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. - -As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: - -9 10 10 10 10 9 9 - -The number of tricks are always seen from declarer’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. - - - - - - - - - - - - - - - - - - - - - -
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedp
int chunkSizeint chunkSize
- -AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. - -The AnalyseAllPlays\* 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. - -Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. - - - - - - - - - - - - -
SetMaxThreadsFreeMemory
int userThreadsvoid
- -SetMaxThreads returns the actual number of threads. - -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 threads 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. - -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. - -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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. - -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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. - -It may be possible, 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. - -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. - -It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. - -## Return codes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a -different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) -Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. -Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, -AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, -ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From 583c805f0c99654d27b196254467082fa5d0283f Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 21:40:35 +0100 Subject: [PATCH 132/199] trying to get rid of dds.md --- doc/dll-description.md | 1358 ---------------------------------------- 1 file changed, 1358 deletions(-) delete mode 100644 doc/dll-description.md diff --git a/doc/dll-description.md b/doc/dll-description.md deleted file mode 100644 index 452d2ca3..00000000 --- a/doc/dll-description.md +++ /dev/null @@ -1,1358 +0,0 @@ -Bo Haglund, Soren Hein, Bob Richardson - -Rev X, 2014-11-16 - -Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ - -# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 -## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. - -Return codes are given at the end. - -Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! - -## The Basic Functions - -The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. - -### The Multi-Thread Double Dummy Solver Functions - -The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. - -To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. - -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. - -The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. - -Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. - -### The PAR Calculation Functions - -The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. - -Two alternatives are given: - -1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. -2. The dealer hand is assumed to “start the bidding”. - -The presentation of the par score and contracts are given in alternative formats. - -The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. - -The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. - -It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. - -The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. - -### Double Dummy Value Analyser Functions - -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionArgumentsFormatComment
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge -of the dealer.
struct parResultsDealer \*presp
int dealer
int vulnerable
 
DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster \* presp
int dealer
int vulnerable
 
ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char \*resp
 
SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
int vulnerable
 
ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char \*resp
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTableResults \*tablep
struct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults \*tablep
int vulnerable
struct parResults \*presp
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
struct solvedPlay \*solvedp
int thrId
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
struct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin \*plp
struct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN \*plpPBN
struct solvedPlays \*solvedp
int chunkSize
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
ErrorMessageint code Turns a return code into an error message string.
-
- -## Data structure -Common encodings are as follows - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
StructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
StructFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
StructFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
StructFieldComment
parTextResultschar parText[2][128];
int equal;
StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
StructFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
StructFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
StructFieldComment
solvedPlayint number;
int tricks[53];Starting position and up to 52 cards
StructFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- -## Functions - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
- -SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. - -SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. - -If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. - -SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. - -There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. - -The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. - -For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
targetsolutionscomment
-11Find the maximum number of tricks for the side to -play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to -play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with -score set to 0.
02Return all cards that legal to play, with score set to -0.
1 .. 131If score is -1: Target cannot be reached.
-If score is 0: In fact no tricks at all can be won.
-If score is > 0: score will always equal target, even if more tricks can be won.
-One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
-If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
- -Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, -and we may use it for something else in the future. If you think you need it, let us know! - -“Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. - -1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` - -2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` - -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` - -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` - - - - - - - - - - - - - - - -
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablep
- -CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. - - - - - - - - - - - - - - - - - - - - - - - - -
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults \*prespstruct allParResults \*presp
- -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. - -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: - - - - - - - - - - - - - - - - - - - - - - - - -
Number of strainsMaximum number of DD tables
532
440
353
280
1160
- - - - - - - - - - - - - - - - - - -
SolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp
int chunkSizeint chunkSize
- -`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. - -`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. - -The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. - -It is important to understand the parallelism and the concept of a chunk. - -If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. - -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. - -No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. - -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! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResults \*prespstruct parResultsDealer \*presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults \*tablep 
struct parResultsDealer \*sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResultsMaster \* prespstruct parResultsMaster \* presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
char \*respstruct parTextResults \*resp
- -The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. - -Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. - -The `vulnerable` parameter is given using Vulnerable encoding. - -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. - -The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. - -The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). - -In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. - -There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. - -Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: - -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. -* “NS:NS 23S,N 23H”: Only North makes 3 hearts. -* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. - -DealerPar() and SidesPar() give each par contract as a separate text string: - -* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. -* “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. -* SidesPar() give the par contract text strings as described above for each side. - -DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. - -After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. -Output example from ConvertToDealerTextFormat: - -“Par 110: NS 2S NS 2H” - -Output examples from ConvertToSidesTextFormat: - -“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT
-EW Par 120: W 1NT+1” when it matters who starts the bidding. - - - - - - - - - - - - - - - - - - - - - -
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedp
int thrIdint thrId
- -AnalysePlayPBN is just like AnalysePlayBin, except for the input format. - -The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. - -As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: - -9 10 10 10 10 9 9 - -The number of tricks are always seen from declarer’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. - - - - - - - - - - - - - - - - - - - - - -
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedp
int chunkSizeint chunkSize
- -AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. - -The AnalyseAllPlays\* 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. - -Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. - - - - - - - - - - - - -
SetMaxThreadsFreeMemory
int userThreadsvoid
- -SetMaxThreads returns the actual number of threads. - -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 threads 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. - -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. - -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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. - -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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. - -It may be possible, 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. - -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. - -It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. - -## Return codes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a -different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) -Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. -Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, -AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, -ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From 85b453c4d87651ad0bcfa64d22df92809fcdd8ee Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 08:48:21 +0100 Subject: [PATCH 133/199] First part of converting dds DOC to md --- dds.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 dds.md diff --git a/dds.md b/dds.md new file mode 100644 index 00000000..a8414f41 --- /dev/null +++ b/dds.md @@ -0,0 +1,49 @@ +Bo Haglund, Bob Richardson +Rev V, 2014-10-14 +Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ + +# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +## Callable functions +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +Return codes are given at the end. + +Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! + +## The Basic Functions + +The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. + +### The Multi-Thread Double Dummy Solver Functions + +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. + +To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. + +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. + +The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. + +The call `FreeMemory` causes DDS to give up its dynamically allocated memory. + +### The PAR Calculation Functions + +The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. + +Two alternatives are given: + +1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. +2. The dealer hand is assumed to “start the bidding”. + +The presentation of the par score and contracts are given in alternative formats. + +The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. + +The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. + +It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. + +The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. + +### Double Dummy Value Analyser Functions + +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file From ed476e811326072b2c92a14e03cc5273cbf09dc2 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 08:48:21 +0100 Subject: [PATCH 134/199] First part of converting dds DOC to md --- doc/dll-description.md | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 doc/dll-description.md diff --git a/doc/dll-description.md b/doc/dll-description.md new file mode 100644 index 00000000..a8414f41 --- /dev/null +++ b/doc/dll-description.md @@ -0,0 +1,49 @@ +Bo Haglund, Bob Richardson +Rev V, 2014-10-14 +Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ + +# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +## Callable functions +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +Return codes are given at the end. + +Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! + +## The Basic Functions + +The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. + +### The Multi-Thread Double Dummy Solver Functions + +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. + +To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. + +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. + +The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. + +The call `FreeMemory` causes DDS to give up its dynamically allocated memory. + +### The PAR Calculation Functions + +The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. + +Two alternatives are given: + +1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. +2. The dealer hand is assumed to “start the bidding”. + +The presentation of the par score and contracts are given in alternative formats. + +The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. + +The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. + +It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. + +The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. + +### Double Dummy Value Analyser Functions + +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file From 54eb1d22f06cbd8737e06e6e0faaec506f013246 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:09:33 +0100 Subject: [PATCH 135/199] First try at the big table in dss.md --- dds.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dds.md b/dds.md index a8414f41..d6d7b6c7 100644 --- a/dds.md +++ b/dds.md @@ -1,5 +1,7 @@ Bo Haglund, Bob Richardson + Rev V, 2014-10-14 + Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ # Description of the DLL functions supported in Double Dummy Problem Solver 2.7 @@ -46,4 +48,11 @@ The par calculation is executed using a single thread. But the calculation is ve ### Double Dummy Value Analyser Functions -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. + +------------------------------------------------------------------- +Function | Arguments | Format | Comment +------------------------------------------------------------------- +| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | +| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | + From 60cbfa15da122a3ef2ce0fcaf27c42c87afd1794 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:09:33 +0100 Subject: [PATCH 136/199] First try at the big table in dss.md --- doc/dll-description.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index a8414f41..d6d7b6c7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -1,5 +1,7 @@ Bo Haglund, Bob Richardson + Rev V, 2014-10-14 + Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ # Description of the DLL functions supported in Double Dummy Problem Solver 2.7 @@ -46,4 +48,11 @@ The par calculation is executed using a single thread. But the calculation is ve ### Double Dummy Value Analyser Functions -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. \ No newline at end of file +The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. + +------------------------------------------------------------------- +Function | Arguments | Format | Comment +------------------------------------------------------------------- +| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | +| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | + From 766f544a5e093111701f67089cb7db0754592e6d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:16:58 +0100 Subject: [PATCH 137/199] Second try at the big table in dss.md --- dds.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/dds.md b/dds.md index d6d7b6c7..7121c37d 100644 --- a/dds.md +++ b/dds.md @@ -51,8 +51,19 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. ------------------------------------------------------------------- -Function | Arguments | Format | Comment +Function | Arguments | Format | Comment | ------------------------------------------------------------------- -| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | -| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | Binary | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +------------------------------------------------------------------------ From 173c4f0effce7a4a925f737f798c321f70fc8e1b Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:16:58 +0100 Subject: [PATCH 138/199] Second try at the big table in dss.md --- doc/dll-description.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index d6d7b6c7..7121c37d 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -51,8 +51,19 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. ------------------------------------------------------------------- -Function | Arguments | Format | Comment +Function | Arguments | Format | Comment | ------------------------------------------------------------------- -| `SolveBoard` | struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | Binary | The most basic function, solves a single hand from the beginning or from later play | -| `SolveBoardPBN` | struct dealPBN dlPBN, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex | PBN |As SolveBoard, but with PBN deal format. | +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | Binary | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +------------------------------------------------------------------------ From b1647063fd4893cba5bbf2bc9cad238ec969b071 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:22:25 +0100 Subject: [PATCH 139/199] Third try at the big table in dss.md --- dds.md | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/dds.md b/dds.md index 7121c37d..34bcd527 100644 --- a/dds.md +++ b/dds.md @@ -50,20 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -------------------------------------------------------------------- -Function | Arguments | Format | Comment | -------------------------------------------------------------------- -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | Binary | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | ------------------------------------------------------------------------- +| Function | Arguments | Format | Comment | +------------------|---------------------------|--------|---------------------------| +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | From 60b4b33944a7ca7be4739697a091aacdf4a22c7c Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:22:25 +0100 Subject: [PATCH 140/199] Third try at the big table in dss.md --- doc/dll-description.md | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 7121c37d..34bcd527 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,20 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -------------------------------------------------------------------- -Function | Arguments | Format | Comment | -------------------------------------------------------------------- -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | Binary | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | ------------------------------------------------------------------------- +| Function | Arguments | Format | Comment | +------------------|---------------------------|--------|---------------------------| +| `SolveBoard` | struct deal dl | Binary | The most basic function, | +| | int target | | solves a single hand from | +| | int solutions | | the beginning or from | +| | int mode | | later play | +| | struct futureTricks *futp | | | +| | int threadIndex | | | +| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | +| | int target | | PBN deal format. | +| | int solutions | | | +| | int mode | | | +| | struct futureTricks *futp | | | +| | int threadIndex | | | From 1326e925a4702095390525414460c6e98c01d33e Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:37:48 +0100 Subject: [PATCH 141/199] Next try at the big table in dss.md, now with embedded HTL table --- dds.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/dds.md b/dds.md index 34bcd527..5af61ad7 100644 --- a/dds.md +++ b/dds.md @@ -50,18 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -| Function | Arguments | Format | Comment | -------------------|---------------------------|--------|---------------------------| -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | - + + + + + + + + + + + + + + +
FunctionArgumentsFormatComment
`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play
`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format.
\ No newline at end of file From 96b2da3adc87052af6ad374abdb224eeffae33ff Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:37:48 +0100 Subject: [PATCH 142/199] Next try at the big table in dss.md, now with embedded HTL table --- doc/dll-description.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 34bcd527..5af61ad7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,18 +50,18 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. -| Function | Arguments | Format | Comment | -------------------|---------------------------|--------|---------------------------| -| `SolveBoard` | struct deal dl | Binary | The most basic function, | -| | int target | | solves a single hand from | -| | int solutions | | the beginning or from | -| | int mode | | later play | -| | struct futureTricks *futp | | | -| | int threadIndex | | | -| `SolveBoardPBN` | struct dealPBN dlPBN | PBN | As SolveBoard, but with | -| | int target | | PBN deal format. | -| | int solutions | | | -| | int mode | | | -| | struct futureTricks *futp | | | -| | int threadIndex | | | - + + + + + + + + + + + + + + +
FunctionArgumentsFormatComment
`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play
`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format.
\ No newline at end of file From e13b097c8ba5d66d62bb7974568fa6a0a909bef8 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:55:36 +0100 Subject: [PATCH 143/199] Still experimenting with HTML in mrkdown --- dds.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dds.md b/dds.md index 5af61ad7..54ef1a86 100644 --- a/dds.md +++ b/dds.md @@ -58,10 +58,10 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format. +`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. \ No newline at end of file From 860216f2d6e616ec96a19d9444acace1087d7ee8 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:55:36 +0100 Subject: [PATCH 144/199] Still experimenting with HTML in mrkdown --- doc/dll-description.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 5af61ad7..54ef1a86 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,10 +58,10 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`
  • struct deal dl
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
BinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`
  • struct dealPBN dlPBN
  • int target
  • int target
  • int solutions
  • int mode
  • struct futureTricks *futp
  • int threadIndex
PBNAs SolveBoard, but with PBN deal format. +`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. \ No newline at end of file From ce1c75242b08b7b3fc0a01dd5d2a64e8f9e5dea9 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:59:54 +0100 Subject: [PATCH 145/199] That was ugly. Next try --- dds.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/dds.md b/dds.md index 54ef1a86..434dd758 100644 --- a/dds.md +++ b/dds.md @@ -58,10 +58,42 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + +int threadIndex + + +`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. + + +int target + + +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + + +int threadIndex \ No newline at end of file From 6622ddcfa05b308adf562f6f827c08aa002e00d3 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 09:59:54 +0100 Subject: [PATCH 146/199] That was ugly. Next try --- doc/dll-description.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 54ef1a86..434dd758 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,10 +58,42 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlint targetint solutionsint modestruct futureTricks *futpint threadIndexBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play -`SolveBoardPBN`struct dealPBN dlPBNint targetint targetint solutionsint modestruct futureTricks *futpint threadIndexPBNAs SolveBoard, but with PBN deal format. +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + +int threadIndex + + +`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. + + +int target + + +int target + + +int solutions + + +int mode + + +struct futureTricks *futp + + +int threadIndex \ No newline at end of file From c6dbec3e4a17fbe88a19475434204e7882bd58b0 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:01:25 +0100 Subject: [PATCH 147/199] That was ugly. Next try --- dds.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 434dd758..105602d7 100644 --- a/dds.md +++ b/dds.md @@ -58,7 +58,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play int target From dc1534b204351f9525db7d035986d4a5e0f175e4 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:01:25 +0100 Subject: [PATCH 148/199] That was ugly. Next try --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 434dd758..105602d7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -58,7 +58,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play int target From ac0ff09c2b5834d5f232c62f212ed3357d38c23f Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:02:23 +0100 Subject: [PATCH 149/199] Much better now --- dds.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/dds.md b/dds.md index 105602d7..11033a54 100644 --- a/dds.md +++ b/dds.md @@ -81,9 +81,6 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int target -int target - - int solutions From 0cdd13f1ca23f4e2c7a835b642ba3aefdab5d7ad Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sat, 8 Nov 2014 10:02:23 +0100 Subject: [PATCH 150/199] Much better now --- doc/dll-description.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 105602d7..11033a54 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -81,9 +81,6 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int target -int target - - int solutions From d4c06d137c022ffa56c97ae5742e1590cbd16f6d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:27:49 +0100 Subject: [PATCH 151/199] Working examples --- dds.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dds.md b/dds.md index 11033a54..23fac1dc 100644 --- a/dds.md +++ b/dds.md @@ -50,6 +50,7 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. + @@ -75,6 +76,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal + From 51ed6c4d3abbc6616b512689135f68c6ba85154d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:27:49 +0100 Subject: [PATCH 152/199] Working examples --- doc/dll-description.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/dll-description.md b/doc/dll-description.md index 11033a54..23fac1dc 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -50,6 +50,7 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. +
int threadIndex
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
@@ -75,6 +76,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal + From 7953f1b6bd732881d7bf66d8f331389505b0332c Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:29:32 +0100 Subject: [PATCH 153/199] Working on dds.md --- dds.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dds.md b/dds.md index 23fac1dc..884887d7 100644 --- a/dds.md +++ b/dds.md @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -77,7 +77,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + From 66b1845348758f179c063f542974991d362004f0 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 06:29:32 +0100 Subject: [PATCH 154/199] Working on dds.md --- doc/dll-description.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 23fac1dc..884887d7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -77,7 +77,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + From 69ee5e9cceb03933dfcc389bcc2a2e5280e61c36 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 07:22:00 +0100 Subject: [PATCH 155/199] Added .gitignore --- dds.md | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 884887d7..f3ec539a 100644 --- a/dds.md +++ b/dds.md @@ -75,8 +75,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -94,5 +94,88 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +tr> + + + + + + + + +
int threadIndex
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later playSolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
`SolveBoard`struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later playSolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
 
`SolveBoardPBN`struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int threadIndex
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format.
struct solvedBoards *solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
\ No newline at end of file From 613c775f42093534e7d6ca5f62c578ef795b6e91 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 18 Nov 2014 07:22:00 +0100 Subject: [PATCH 156/199] Added .gitignore --- doc/dll-description.md | 85 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 884887d7..f3ec539a 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -75,8 +75,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int threadIndex -   + SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. @@ -94,5 +94,88 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int threadIndex +  + +CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) + + +struct ddTableResults * tablep + +  + +CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. + + +struct ddTableResults * tablep + +  + +CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded. + + +int mode + + +int trumpFilter[5] + + +struct ddTablesRes *resp + + +struct allParResults *pres + +  + +CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format. + + +int mode + + +int trumpFilter[5] + + +struct ddTablesRes *resp + + +struct allParResults *pres + +  + +SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format. + + +struct solvedBoards *solvedp + +  + +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. + + +struct solvedBoards *solvedp + + +int chunkSize + +  + +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! + + +struct solvedBoards *solvedp + + +int chunkSize + +tr>  + +SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. + + +struct solvedBoards *solvedp + + +int chunkSize + \ No newline at end of file From 11aa4d2db2a4070e648dd0db4ade5f6fad468870 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Thu, 20 Nov 2014 08:18:29 +0100 Subject: [PATCH 157/199] All functiond described in dds.md --- dds.md | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 160 insertions(+), 4 deletions(-) diff --git a/dds.md b/dds.md index f3ec539a..a0d82343 100644 --- a/dds.md +++ b/dds.md @@ -149,7 +149,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! struct solvedBoards *solvedp @@ -169,7 +169,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal tr>  -SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -177,5 +177,161 @@ tr>  int chunkSize +  + +Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. + + +struct parResults *presp + + +int vulnerable + +  + +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. + + +struct parResultsDealer *presp + + +int dealer + + +int vulnerable + +  + +DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. + + +struct parResultsMaster * presp + + +int dealer + + +int vulnerable + +  + +ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. + + +char *resp + +  + +SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. + + +struct parResultsDealer *presp + + +int vulnerable + +  + +SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. + + +struct parResultsMaster sidesRes[2] + + +int vulnerable + +  + +ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. + + +char *resp + +  + +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! + + +int vulnerable + + +struct ddTableResults *tablep + + +struct parResults *presp + +  + +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! + + +struct ddTableResults *tablep + + +int vulnerable + + +struct parResults *presp + +  + +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. + + +struct playTraceBin play + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. + + +struct playTracePBN playPBN + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. + + +struct playTracesBin *plp + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. + + +struct playTracesPBN *plpPBN + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. + +  + +FreeMemoryvoidPBNFrees DDS allocated dynamical memory. + - \ No newline at end of file + From 1e72aa48ba235aae906f953f922bbf549a60962a Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Thu, 20 Nov 2014 08:18:29 +0100 Subject: [PATCH 158/199] All functiond described in dds.md --- doc/dll-description.md | 164 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 4 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index f3ec539a..a0d82343 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -149,7 +149,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! struct solvedBoards *solvedp @@ -169,7 +169,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal tr>  -SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. struct solvedBoards *solvedp @@ -177,5 +177,161 @@ tr>  int chunkSize +  + +Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. + + +struct parResults *presp + + +int vulnerable + +  + +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. + + +struct parResultsDealer *presp + + +int dealer + + +int vulnerable + +  + +DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. + + +struct parResultsMaster * presp + + +int dealer + + +int vulnerable + +  + +ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. + + +char *resp + +  + +SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. + + +struct parResultsDealer *presp + + +int vulnerable + +  + +SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. + + +struct parResultsMaster sidesRes[2] + + +int vulnerable + +  + +ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. + + +char *resp + +  + +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! + + +int vulnerable + + +struct ddTableResults *tablep + + +struct parResults *presp + +  + +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! + + +struct ddTableResults *tablep + + +int vulnerable + + +struct parResults *presp + +  + +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. + + +struct playTraceBin play + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. + + +struct playTracePBN playPBN + + +struct solvedPlay *solvedp + + +int thrId + +  + +AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. + + +struct playTracesBin *plp + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. + + +struct playTracesPBN *plpPBN + + +struct solvedPlays *solvedp + + +int chunkSize + +  + +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. + +  + +FreeMemoryvoidPBNFrees DDS allocated dynamical memory. + - \ No newline at end of file + From 29b521d4a64de9f4f9d69a01e55215deda53fa3f Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:46:58 +0100 Subject: [PATCH 159/199] Finished tables in dds.md --- dds.md | 460 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) diff --git a/dds.md b/dds.md index a0d82343..7283e59e 100644 --- a/dds.md +++ b/dds.md @@ -335,3 +335,463 @@ tr>  +### Data sructure +Common encodings are as follows + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
+ + + + + + + + + + + +
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding PBN encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
+ + + + + + + + + + + +
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
+ + + + + + + + + + + +
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
+ + + + + + + + + + + + + + +
structFieldComment
parTextResultschar parText[2][128];
int equal;
+ + + + + + + + + + + + + + + + + +
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
+ + + + + + + + + + + + + + +
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
+ + + + + + + + + + + + + + +
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlayint number;
int tricks[53];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS / 10];
\ No newline at end of file From 8455e991c87cf6923b8220974b6f8d9d55d8ba17 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:46:58 +0100 Subject: [PATCH 160/199] Finished tables in dds.md --- doc/dll-description.md | 460 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) diff --git a/doc/dll-description.md b/doc/dll-description.md index a0d82343..7283e59e 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -335,3 +335,463 @@ tr>  +### Data sructure +Common encodings are as follows + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
+ + + + + + + + + + + +
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding PBN encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
+ + + + + + + + + + + +
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
+ + + + + + + + + + + + + + +
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
+ + + + + + + + + + + + + + +
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
+ + + + + + + + + + + +
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
+ + + + + + + + + + + + + + + + + +
structFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
+ + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
+ + + + + + + + + + + + + + +
structFieldComment
parTextResultschar parText[2][128];
int equal;
+ + + + + + + + + + + + + + + + + +
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
+ + + + + + + + + + + + + + +
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
+ + + + + + + + + + + + + + +
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlayint number;
int tricks[53];
+ + + + + + + + + + + + + + +
structFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS / 10];
\ No newline at end of file From 3de83ed059bdc2525ca5e0ecf7d3deb5a31c38da Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:59:06 +0100 Subject: [PATCH 161/199] Finished tables in dds.md --- dds.md | 218 +++++++++++++++++++++++---------------------------------- 1 file changed, 86 insertions(+), 132 deletions(-) diff --git a/dds.md b/dds.md index 7283e59e..14cb1eae 100644 --- a/dds.md +++ b/dds.md @@ -415,15 +415,12 @@ Common encodings are as follows unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. - - - - + + + - - @@ -439,57 +436,49 @@ Common encodings are as follows - -
structFieldComment
dealPBNint trump;Suit encoding
char remainCards[80];Remaining cards. PBN encoding.
- - + + + + - - - -
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
- - + + + + - - @@ -505,15 +494,13 @@ Common encodings are as follows - -
structFieldComment
boardsint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + + - - @@ -529,15 +516,12 @@ Common encodings are as follows - -
structFieldComment
boardsPBNint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + - - @@ -556,84 +540,72 @@ Common encodings are as follows - -
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
- - + + + + - - - -
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
- - + + + + - - - -
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
- - + + + + - - - -
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
- - + + + + - - - -
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
- - + + + + - - @@ -643,15 +615,13 @@ Common encodings are as follows - -
structFieldComment
parResultsDealerint number;
char contracts[10][10];
- - + + + + - - @@ -661,15 +631,13 @@ Common encodings are as follows - -
structFieldComment
parResultsMasterint score;
struct contractType contracts[10];
- - + + + + - - @@ -685,30 +653,26 @@ Common encodings are as follows - -
structFieldComment
contractTypeint underTricks;
int seats;
- - + + + + - - - -
structFieldComment
parTextResultschar parText[2][128];
int equal;
- - + + + + - - @@ -718,75 +682,65 @@ Common encodings are as follows - -
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int rank[52];Encoding 2 .. 14 (not Card encoding).
- - + + + + - - - -
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
- - + + + + - - - -
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
solvedPlayint number;
int tricks[53];
- - + + + + - - From 681fc434381c912dd573522a80f2af4fa47624e7 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 2 Dec 2014 16:59:06 +0100 Subject: [PATCH 162/199] Finished tables in dds.md --- doc/dll-description.md | 218 ++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 132 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 7283e59e..14cb1eae 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -415,15 +415,12 @@ Common encodings are as follows - -
structFieldComment
solvedPlaysint noOfBoards;
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
- - + + + - - @@ -439,57 +436,49 @@ Common encodings are as follows - -
structFieldComment
dealPBNint trump;Suit encoding
char remainCards[80];Remaining cards. PBN encoding.
- - + + + + - - - -
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDeal deals[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
- - + + + + - - @@ -505,15 +494,13 @@ Common encodings are as follows - -
structFieldComment
boardsint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + + - - @@ -529,15 +516,12 @@ Common encodings are as follows - -
structFieldComment
boardsPBNint noOfBoards;Number of boards
int mode[MAXNOOFBOARDS];See SolveBoard
- - + + + - - @@ -556,84 +540,72 @@ Common encodings are as follows - -
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
- - + + + + - - - -
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
- - + + + + - - - -
structFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
- - + + + + - - - -
structFieldComment
ddTablesResint noOfBoards;
struct ddTableResults results[MAXNOOFBOARDS/4];
- - + + + + - - - -
structFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
- - + + + + - - - -
structFieldComment
allParResultsstruct parResults[MAXNOOFBOARDS/20];
- - + + + + - - @@ -643,15 +615,13 @@ Common encodings are as follows - -
structFieldComment
parResultsDealerint number;
char contracts[10][10];
- - + + + + - - @@ -661,15 +631,13 @@ Common encodings are as follows - -
structFieldComment
parResultsMasterint score;
struct contractType contracts[10];
- - + + + + - - @@ -685,30 +653,26 @@ Common encodings are as follows - -
structFieldComment
contractTypeint underTricks;
int seats;
- - + + + + - - - -
structFieldComment
parTextResultschar parText[2][128];
int equal;
- - + + + + - - @@ -718,75 +682,65 @@ Common encodings are as follows - -
structFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int rank[52];Encoding 2 .. 14 (not Card encoding).
- - + + + + - - - -
structFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
- - + + + + - - - -
structFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
- - + + + + - - - -
structFieldComment
solvedPlayint number;
int tricks[53];
- - + + + + - - From e1725c8cdb2e07e2903fee2542802fb4ac9ab5ff Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 01:40:49 +0100 Subject: [PATCH 163/199] Added a few pages --- dds.md | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 14cb1eae..a890c51c 100644 --- a/dds.md +++ b/dds.md @@ -748,4 +748,105 @@ Common encodings are as follows -
structFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS / 10];
\ No newline at end of file + + +### Functions + + + + + + + + + + + + + + + + + + + + + + + + + + +
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,
int threadIndexint threadIndex
+SolveBoardPBN is just like SolveBoard, except for the input format. + +SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. + +SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. + +There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. + +The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. + +For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
targetsolutionscomment
-11Find the maximum number of tricks for the side to +play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to +play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with +score set to 0.
02Return all cards that legal to play, with score set to +0.
1 .. 131If score is -1: Target cannot be reached.
+If score is 0: In fact no tricks at all can be won.
+If score is > 0: score will always equal target, even if more tricks can be won.
+One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
+If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
+“Reuse” means “reuse the transposition table from the previous run with the same thread number”. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. + +1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + From 4c459209ecec97ade2e7d08c149a1d634c0bb28d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 01:40:49 +0100 Subject: [PATCH 164/199] Added a few pages --- doc/dll-description.md | 103 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 14cb1eae..a890c51c 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -748,4 +748,105 @@ Common encodings are as follows struct solvedPlay solved[MAXNOOFBOARDS / 10]; - \ No newline at end of file + + +### Functions + + + + + + + + + + + + + + + + + + + + + + + + + + +
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,
int threadIndexint threadIndex
+SolveBoardPBN is just like SolveBoard, except for the input format. + +SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. + +SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. + +There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. + +The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. + +For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
targetsolutionscomment
-11Find the maximum number of tricks for the side to +play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to +play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with +score set to 0.
02Return all cards that legal to play, with score set to +0.
1 .. 131If score is -1: Target cannot be reached.
+If score is 0: In fact no tricks at all can be won.
+If score is > 0: score will always equal target, even if more tricks can be won.
+One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
+If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
+“Reuse” means “reuse the transposition table from the previous run with the same thread number”. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. + +1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + From 4a25f64e82965f50a88cfd39e850824de78dce2d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 04:48:51 +0100 Subject: [PATCH 165/199] All text typed. --- dds.md | 471 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 466 insertions(+), 5 deletions(-) diff --git a/dds.md b/dds.md index a890c51c..c4887f0c 100644 --- a/dds.md +++ b/dds.md @@ -167,7 +167,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int chunkSize -tr>  +  SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. @@ -845,8 +845,469 @@ If the target cannot be achieved, only one card is returned with the score set a “Reuse” means “reuse the transposition table from the previous run with the same thread number”. For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. -1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` -2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` +1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` + +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` + +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + + + + + + + + + + + + + + + +
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults * tablepstruct ddTableResults * tablep
+CalcDDtablePBN is just like CalcDDtable, except for the input format. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. + + + + + + + + + + + + + + + + + + + + + + + + +
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *resp
struct allParResults *prespstruct allParResults *presp
+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. +The “mode” parameter contains the vulnerability (Vulnerable encoding) 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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + + + + + + + + + + + + + + + + + + + + + + + + +
Number of strainsMaximum number of DD tables
510
412
316
225
150
+ + + + + + + + + + + + + + + + + + +
SolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
+`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. +`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; +don’t use it. +The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +It is important to understand the parallelism and the concept of a chunk. +If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused +within a chunk. +No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: +* The same board is played at two tables of a team match. +* A board is played at 10 tables in a pairs tournament. +* The trump suit is the same, and there are very minor differences in the rest. +The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. +Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParDealerPar
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults *tablep 
struct parResultsDealer *sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster * prespstruct parResultsMaster * presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster *presstruct parResultsMaster *pres
char *respstruct parTextResults *resp
+The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. + +Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. + +The `vulnerable` parameter is given using Vulnerable encoding. + +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. + +The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. + +The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). + +In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. + +There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. + +Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: + +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,N 23H”: Only North makes 3 hearts. +* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. + +DealerPar() and SidesPar() give each par contract as a separate text string: + +* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. +* “3N-EW” means that E and W can both make exactly 3NT. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* SidesPar() give the par contract text strings as described above for each side. + +DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. + +After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. +Output example from ConvertToDealerTextFormat: + +“Par 110: NS 2S NS 2H” + +Output examples from ConvertToSidesTextFormat: + +“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. +”NS Par -120: W 2NT +EW Par 120: W 1NT+1” when it matters who starts the bidding. + + + + + + + + + + + + + + + + + + + + + +
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
+ +AnalysePlayPBN is just like AnalysePlayBin, except for the input format. + +The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. + +As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: + +9 10 10 10 10 9 9 + +The number of tricks are always seen from declarer’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. + + + + + + + + + + + + + + + + + + + + + +
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards *bopstruct boardsPBN *bopPBN
struct playTracesBin *plpstruct playTracesPBN *plpPBN
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
+AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. + +The AnalyseAllPlays* 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. + +Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. + + + + + + + + + + + + +
SetMaxThreadsFreeMemory
int userThreadsvoid
+SetMaxThreads returns the actual number of threads. + +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 threads 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. + +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. + +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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. + +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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. + +=== Return codes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a +different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. +Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +ConvertToDealerTextFormat, ConvertToSidesTextFormat
From 597ec55e10bf0d1d30db3653cb812f8bb3ac271d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 04:48:51 +0100 Subject: [PATCH 166/199] All text typed. --- doc/dll-description.md | 471 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 466 insertions(+), 5 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index a890c51c..c4887f0c 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -167,7 +167,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal int chunkSize -tr>  +  SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded. @@ -845,8 +845,469 @@ If the target cannot be achieved, only one card is returned with the score set a “Reuse” means “reuse the transposition table from the previous run with the same thread number”. For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. -1 st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` -2 nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` +1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` +2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` + +3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` + +4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` + + + + + + + + + + + + + + + +
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults * tablepstruct ddTableResults * tablep
+CalcDDtablePBN is just like CalcDDtable, except for the input format. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. + + + + + + + + + + + + + + + + + + + + + + + + +
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *resp
struct allParResults *prespstruct allParResults *presp
+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. +The “mode” parameter contains the vulnerability (Vulnerable encoding) 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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + + + + + + + + + + + + + + + + + + + + + + + + +
Number of strainsMaximum number of DD tables
510
412
316
225
150
+ + + + + + + + + + + + + + + + + + +
SolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
+`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. +`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; +don’t use it. +The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +It is important to understand the parallelism and the concept of a chunk. +If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused +within a chunk. +No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: +* The same board is played at two tables of a team match. +* A board is played at 10 tables in a pairs tournament. +* The trump suit is the same, and there are very minor differences in the rest. +The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. +Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParDealerPar
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults *tablep 
struct parResultsDealer *sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster * prespstruct parResultsMaster * presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster *presstruct parResultsMaster *pres
char *respstruct parTextResults *resp
+The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. + +Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. + +The `vulnerable` parameter is given using Vulnerable encoding. + +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. + +The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. + +The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). + +In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. + +There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. + +Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: + +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,N 23H”: Only North makes 3 hearts. +* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. + +DealerPar() and SidesPar() give each par contract as a separate text string: + +* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. +* “3N-EW” means that E and W can both make exactly 3NT. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* SidesPar() give the par contract text strings as described above for each side. + +DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. + +After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. +Output example from ConvertToDealerTextFormat: + +“Par 110: NS 2S NS 2H” + +Output examples from ConvertToSidesTextFormat: + +“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. +”NS Par -120: W 2NT +EW Par 120: W 1NT+1” when it matters who starts the bidding. + + + + + + + + + + + + + + + + + + + + + +
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
+ +AnalysePlayPBN is just like AnalysePlayBin, except for the input format. + +The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. + +As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: + +9 10 10 10 10 9 9 + +The number of tricks are always seen from declarer’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. + + + + + + + + + + + + + + + + + + + + + +
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards *bopstruct boardsPBN *bopPBN
struct playTracesBin *plpstruct playTracesPBN *plpPBN
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
+AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. + +The AnalyseAllPlays* 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. + +Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. + + + + + + + + + + + + +
SetMaxThreadsFreeMemory
int userThreadsvoid
+SetMaxThreads returns the actual number of threads. + +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 threads 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. + +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. + +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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. + +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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. + +=== Return codes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a +different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. +Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +ConvertToDealerTextFormat, ConvertToSidesTextFormat
From b31074ce6314b34436d4571b263bba3b47d84707 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 05:55:42 +0100 Subject: [PATCH 167/199] All changes made from diff. Document is now on par with v 2.8.0 --- dds.md | 153 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 94 insertions(+), 59 deletions(-) diff --git a/dds.md b/dds.md index c4887f0c..97a95458 100644 --- a/dds.md +++ b/dds.md @@ -1,31 +1,32 @@ -Bo Haglund, Bob Richardson +Bo Haglund, Soren Hein, Bob Richardson -Rev V, 2014-10-14 +Rev X, 2014-11-16 Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ -# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 ## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. + Return codes are given at the end. Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! ## The Basic Functions -The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. +The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. -The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. +The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. -The call `FreeMemory` causes DDS to give up its dynamically allocated memory. +Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. ### The PAR Calculation Functions @@ -142,7 +143,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format. +SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! struct solvedBoards *solvedp @@ -189,7 +190,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +of the dealer. struct parResultsDealer *presp @@ -327,12 +329,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) + +  + +FreeMemoryvoid Frees DDS allocated dynamical memory.   -FreeMemoryvoidPBNFrees DDS allocated dynamical memory. +ErrorMessageint code Turns a return code into an error message string. + + ### Data sructure @@ -413,7 +421,7 @@ Common encodings are as follows int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. +unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. @@ -454,10 +462,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTables;Number of DD table deals in structure +ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableDeal deals[MAXNOOFBOARDS/4]; +struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINS @@ -535,7 +543,7 @@ Common encodings are as follows int rank[13];Rank of the returned card. Value range 2-14. -int equals[13];Lower-ranked equals. Holding PBN encoding. +int equals[13];Lower-ranked equals. Holding encoding. int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks. @@ -558,7 +566,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. @@ -571,17 +579,17 @@ Common encodings are as follows structFieldComment -ddTablesResint noOfBoards; +ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableResults results[MAXNOOFBOARDS/4]; +struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINS -structFieldComment +StructFieldComment parResultschar parScore[2][16];First index is NS/EW. Side encoding. @@ -594,17 +602,17 @@ Common encodings are as follows -structFieldComment +StructFieldComment -allParResultsstruct parResults[MAXNOOFBOARDS/20]; +allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table -structFieldComment +StructFieldComment parResultsDealerint number; @@ -620,7 +628,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parResultsMasterint score; @@ -636,7 +644,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment contractTypeint underTricks; @@ -658,7 +666,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parTextResultschar parText[2][128]; @@ -671,7 +679,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -687,7 +695,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -700,7 +708,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesBinint noOfBoards; @@ -713,7 +721,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesPBNint noOfBoards; @@ -726,26 +734,26 @@ Common encodings are as follows -structFieldComment +StructFieldComment solvedPlayint number; -int tricks[53]; +int tricks[53];Starting position and up to 52 cards -structFieldComment +StructFieldComment solvedPlaysint noOfBoards; -struct solvedPlay solved[MAXNOOFBOARDS / 10]; +struct solvedPlay solved[MAXNOOFBOARDS]; @@ -778,10 +786,12 @@ Common encodings are as follows -SolveBoardPBN is just like SolveBoard, except for the input format. +SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. + SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. @@ -842,8 +852,11 @@ If the target cannot be achieved, only one card is returned with the score set a +Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, +and we may use it for something else in the future. If you think you need it, let us know! + “Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. 1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` @@ -896,10 +909,14 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy 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. -The “mode” parameter contains the vulnerability (Vulnerable encoding) for use in the par calculation. It is set to -1 if no par calculation is to be performed. + +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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + +The maximum number of DD tables in a CallAllTables call depends on the number of strains required, see the following table: @@ -909,19 +926,19 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + - + - +
510532
412440
316353
225280
1501160
@@ -929,15 +946,15 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + @@ -945,19 +962,20 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
SolverAllChunksBinSolveAllChunksPBNSolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bopstruct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. -`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; -don’t use it. + +`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. + The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. + It is important to understand the parallelism and the concept of a chunk. + If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused -within a chunk. -No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: -* The same board is played at two tables of a team match. -* A board is played at 10 tables in a pairs tournament. -* The trump suit is the same, and there are very minor differences in the rest. -The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. -Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. + +No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. + +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! @@ -1065,7 +1083,7 @@ Output example from ConvertToDealerTextFormat: Output examples from ConvertToSidesTextFormat: “NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT +”NS Par -120: W 2NT
EW Par 120: W 1NT+1” when it matters who starts the bidding.
@@ -1150,7 +1168,11 @@ DDS then checks whether a number of threads equal to the number of cores will fi 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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. +It may be possible, 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. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. + +It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. === Return codes
@@ -1204,6 +1226,17 @@ different number of boards in its first two arguments. + + + + + + + + + + + @@ -1309,5 +1342,7 @@ AnalyseAllPlaysPBN + +
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From b35949c5609cfbeae0a704e29bc79bfb00aeaa6a Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 05:55:42 +0100 Subject: [PATCH 168/199] All changes made from diff. Document is now on par with v 2.8.0 --- doc/dll-description.md | 153 +++++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 59 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index c4887f0c..97a95458 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -1,31 +1,32 @@ -Bo Haglund, Bob Richardson +Bo Haglund, Soren Hein, Bob Richardson -Rev V, 2014-10-14 +Rev X, 2014-11-16 Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ -# Description of the DLL functions supported in Double Dummy Problem Solver 2.7 +# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 ## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`. +The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. + Return codes are given at the end. Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! ## The Basic Functions -The basic functions `SolveBoard` and `SolveBoardPBN` solve each a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. +The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. +The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. -The number of threads is automatically configured by DDS, taking into account the number of processor cores and available memory. The number of threads can be influenced using the call `SetMaxThreads`. +The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. -The call `FreeMemory` causes DDS to give up its dynamically allocated memory. +Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. ### The PAR Calculation Functions @@ -142,7 +143,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllBoardsstruct boardsPBN *bopPBNAs CalcAllTables, but with PBN deal format. +SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! struct solvedBoards *solvedp @@ -189,7 +190,8 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses dealer. +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +of the dealer. struct parResultsDealer *presp @@ -327,12 +329,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) + +  + +FreeMemoryvoid Frees DDS allocated dynamical memory.   -FreeMemoryvoidPBNFrees DDS allocated dynamical memory. +ErrorMessageint code Turns a return code into an error message string. + + ### Data sructure @@ -413,7 +421,7 @@ Common encodings are as follows int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. +unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. @@ -454,10 +462,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTables;Number of DD table deals in structure +ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableDeal deals[MAXNOOFBOARDS/4]; +struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINS @@ -535,7 +543,7 @@ Common encodings are as follows int rank[13];Rank of the returned card. Value range 2-14. -int equals[13];Lower-ranked equals. Holding PBN encoding. +int equals[13];Lower-ranked equals. Holding encoding. int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks. @@ -558,7 +566,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. @@ -571,17 +579,17 @@ Common encodings are as follows structFieldComment -ddTablesResint noOfBoards; +ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableResults results[MAXNOOFBOARDS/4]; +struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINS -structFieldComment +StructFieldComment parResultschar parScore[2][16];First index is NS/EW. Side encoding. @@ -594,17 +602,17 @@ Common encodings are as follows -structFieldComment +StructFieldComment -allParResultsstruct parResults[MAXNOOFBOARDS/20]; +allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table -structFieldComment +StructFieldComment parResultsDealerint number; @@ -620,7 +628,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parResultsMasterint score; @@ -636,7 +644,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment contractTypeint underTricks; @@ -658,7 +666,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment parTextResultschar parText[2][128]; @@ -671,7 +679,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -687,7 +695,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand. @@ -700,7 +708,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesBinint noOfBoards; @@ -713,7 +721,7 @@ Common encodings are as follows -structFieldComment +StructFieldComment playTracesPBNint noOfBoards; @@ -726,26 +734,26 @@ Common encodings are as follows -structFieldComment +StructFieldComment solvedPlayint number; -int tricks[53]; +int tricks[53];Starting position and up to 52 cards -structFieldComment +StructFieldComment solvedPlaysint noOfBoards; -struct solvedPlay solved[MAXNOOFBOARDS / 10]; +struct solvedPlay solved[MAXNOOFBOARDS]; @@ -778,10 +786,12 @@ Common encodings are as follows -SolveBoardPBN is just like SolveBoard, except for the input format. +SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. + SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. @@ -842,8 +852,11 @@ If the target cannot be achieved, only one card is returned with the score set a +Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, +and we may use it for something else in the future. If you think you need it, let us know! + “Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. 1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` @@ -896,10 +909,14 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy 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. -The “mode” parameter contains the vulnerability (Vulnerable encoding) for use in the par calculation. It is set to -1 if no par calculation is to be performed. + +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. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher. + +The maximum number of DD tables in a CallAllTables call depends on the number of strains required, see the following table: @@ -909,19 +926,19 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + - + - +
510532
412440
316353
225280
1501160
@@ -929,15 +946,15 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + @@ -945,19 +962,20 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
SolverAllChunksBinSolveAllChunksPBNSolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boardsPBN *bopstruct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. -`SolveAllBoards` is an alias for SolveAllChunksPBN with a chunkSize of 1; -don’t use it. + +`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. + The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. + It is important to understand the parallelism and the concept of a chunk. + If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused -within a chunk. -No matter what the chunk size is, the boards are solved in parallel. But if the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. Here are some examples: -* The same board is played at two tables of a team match. -* A board is played at 10 tables in a pairs tournament. -* The trump suit is the same, and there are very minor differences in the rest. -The simulation aims to find out which hand is best as declarer. But CalcAllTables can be a more convenient alternative for this. -Note that the alignment must remain perfect throughout the whole function call: If the chunk size is 2, then a board with an even number and the following board must be very similar. This must be the case even if the board is passed out at one table, or played in the same contract. + +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. + +No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. + +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! @@ -1065,7 +1083,7 @@ Output example from ConvertToDealerTextFormat: Output examples from ConvertToSidesTextFormat: “NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT +”NS Par -120: W 2NT
EW Par 120: W 1NT+1” when it matters who starts the bidding.
@@ -1150,7 +1168,11 @@ DDS then checks whether a number of threads equal to the number of cores will fi 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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. +It may be possible, 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. + +SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. + +It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. === Return codes
@@ -1204,6 +1226,17 @@ different number of boards in its first two arguments. + + + + + + + + + + + @@ -1309,5 +1342,7 @@ AnalyseAllPlaysPBN + +
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From eba940dea8a3ba12b68b255d15c84d7a62c5a195 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 07:56:46 +0100 Subject: [PATCH 169/199] Changes made focussing on Markup syntax --- dds.md | 172 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 91 insertions(+), 81 deletions(-) diff --git a/dds.md b/dds.md index 97a95458..32bef118 100644 --- a/dds.md +++ b/dds.md @@ -18,7 +18,7 @@ The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand a ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. +The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. @@ -51,7 +51,6 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - @@ -72,7 +71,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -90,7 +89,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -100,18 +99,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -120,14 +119,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -136,65 +135,65 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - - + @@ -204,10 +203,10 @@ of the dealer. - + - + @@ -217,24 +216,24 @@ of the dealer. - + - + - + - + - + @@ -244,10 +243,10 @@ of the dealer. - + - + @@ -257,23 +256,23 @@ of the dealer. - + - + - + - + @@ -283,7 +282,7 @@ of the dealer. - + @@ -296,33 +295,33 @@ of the dealer. - + - + - + - + - + - + - + @@ -343,8 +342,10 @@ of the dealer.
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndex
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndexCalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded.SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *prespstruct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int dealer
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster * prespstruct parResultsMaster \* presp
int dealer
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char *respchar \*resp
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char *respchar \*resp
 
int vulnerable
struct ddTableResults *tablepstruct ddTableResults \*tablep
struct parResults *prespstruct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablepstruct ddTableResults \*tablep
int vulnerable
struct parResults *prespstruct parResults \*presp
 
struct playTraceBin play
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId struct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plpstruct playTracesBin \*plp
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBNstruct playTracesPBN \*plpPBN
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
-### Data sructure + +## Data structure Common encodings are as follows + @@ -465,7 +466,7 @@ Common encodings are as follows - + @@ -582,7 +583,7 @@ Common encodings are as follows - + @@ -758,7 +759,8 @@ Common encodings are as follows
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
-### Functions +## Functions + @@ -779,16 +781,17 @@ Common encodings are as follows - +
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
+ SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. -SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. @@ -852,6 +855,7 @@ If the target cannot be achieved, only one card is returned with the score set a + Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, and we may use it for something else in the future. If you think you need it, let us know! @@ -877,12 +881,13 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN -struct ddTableResults * tablepstruct ddTableResults * tablep +struct ddTableResults \* tablepstruct ddTableResults \* tablep + CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. @@ -892,7 +897,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + @@ -901,16 +906,17 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + - +
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealspstruct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint modeint trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *respstruct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults *prespstruct allParResults *prespstruct allParResults \*prespstruct allParResults \*presp
+ 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. +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. 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. @@ -951,21 +957,22 @@ The maximum number of DD tables in a CallAllTables call depends on the number of -struct boards *bopstruct boards *bopstruct boardsPBN *bop +struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop -struct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp +struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp int chunkSizeint chunkSize + `SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. `SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. -The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. It is important to understand the parallelism and the concept of a chunk. @@ -985,10 +992,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResults *prespstruct parResultsDealer *presp +struct parResults \*prespstruct parResultsDealer \*presp int vulnerableint dealer @@ -1003,10 +1010,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or Sidespar  -struct ddTableResults *tablep  +struct ddTableResults \*tablep  -struct parResultsDealer *sidesRes[2]  +struct parResultsDealer \*sidesRes[2]  int vulnerable  @@ -1018,10 +1025,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or DealerParBinSidesParBin -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResultsMaster * prespstruct parResultsMaster * presp +struct parResultsMaster \* prespstruct parResultsMaster \* presp int vulnerableint dealer @@ -1036,13 +1043,14 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or ConvertToDealerTextForamatConvertToSidesTextFormat -struct parResultsMaster *presstruct parResultsMaster *pres +struct parResultsMaster \*presstruct parResultsMaster \*pres -char *respstruct parTextResults *resp +char \*respstruct parTextResults \*resp + The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. @@ -1061,8 +1069,7 @@ There may be several par contracts, for instance 3NT just making and 5C just mak Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. * “NS:NS 23S,N 23H”: Only North makes 3 hearts. * “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. @@ -1070,7 +1077,7 @@ DealerPar() and SidesPar() give each par contract as a separate text string: * “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. * “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. * SidesPar() give the par contract text strings as described above for each side. DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. @@ -1100,7 +1107,7 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding. struct playTraceBin playstruct playTracePBN playPBN -struct solvedPlay *solvedpstruct solvedPlay *solvedp +struct solvedPlay \*solvedpstruct solvedPlay \*solvedp int thrIdint thrId @@ -1126,22 +1133,23 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one -struct boards *bopstruct boardsPBN *bopPBN +struct boards \*bopstruct boardsPBN \*bopPBN -struct playTracesBin *plpstruct playTracesPBN *plpPBN +struct playTracesBin \*plpstruct playTracesPBN \*plpPBN -struct solvedPlays *solvedpstruct solvedPlays *solvedp +struct solvedPlays \*solvedpstruct solvedPlays \*solvedp int chunkSizeint chunkSize + AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. -The AnalyseAllPlays* 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. +The AnalyseAllPlays\* 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. Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. @@ -1157,6 +1165,7 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi + SetMaxThreads returns the actual number of threads. 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 threads than there are processor cores, as this will only require more memory and will not improve performance. Within these constraints, DDS auto-configures the @@ -1174,7 +1183,8 @@ SetMaxThreads can be called multiple times even within the same session. So it i It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. -=== Return codes +## Return codes + @@ -1237,7 +1247,7 @@ different number of boards in its first two arguments. - @@ -1252,13 +1262,13 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + - + - +
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
From 0200135b808457e667a7938512ee0627ff4f9640 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 07:56:46 +0100 Subject: [PATCH 170/199] Changes made focussing on Markup syntax --- doc/dll-description.md | 172 ++++++++++++++++++++++------------------- 1 file changed, 91 insertions(+), 81 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 97a95458..32bef118 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -18,7 +18,7 @@ The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand a ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. +The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. @@ -51,7 +51,6 @@ The par calculation is executed using a single thread. But the calculation is ve The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - @@ -72,7 +71,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -90,7 +89,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -100,18 +99,18 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -120,14 +119,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -136,65 +135,65 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - - + @@ -204,10 +203,10 @@ of the dealer. - + - + @@ -217,24 +216,24 @@ of the dealer. - + - + - + - + - + @@ -244,10 +243,10 @@ of the dealer. - + - + @@ -257,23 +256,23 @@ of the dealer. - + - + - + - + @@ -283,7 +282,7 @@ of the dealer. - + @@ -296,33 +295,33 @@ of the dealer. - + - + - + - + - + - + - + @@ -343,8 +342,10 @@ of the dealer.
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndex
int mode
struct futureTricks *futpstruct futureTricks \*futp
int threadIndexCalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablepstruct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes \*resp
struct allParResults *presstruct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN *bopPBNSolves a number of hands in parallel. Multi-threaded.SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *prespstruct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int dealer
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster * prespstruct parResultsMaster \* presp
int dealer
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char *respchar \*resp
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *prespstruct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char *respchar \*resp
 
int vulnerable
struct ddTableResults *tablepstruct ddTableResults \*tablep
struct parResults *prespstruct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablepstruct ddTableResults \*tablep
int vulnerable
struct parResults *prespstruct parResults \*presp
 
struct playTraceBin play
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId struct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plpstruct playTracesBin \*plp
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBNstruct playTracesPBN \*plpPBN
struct solvedPlays *solvedpstruct solvedPlays \*solvedp
int chunkSize
-### Data sructure + +## Data structure Common encodings are as follows + @@ -465,7 +466,7 @@ Common encodings are as follows - + @@ -582,7 +583,7 @@ Common encodings are as follows - + @@ -758,7 +759,8 @@ Common encodings are as follows
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES * DDS_STRAINSstruct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
-### Functions +## Functions + @@ -779,16 +781,17 @@ Common encodings are as follows - +
int mode,int mode,
struct futureTricks *futp,struct futureTricks *futp,struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
+ SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. -SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard. +SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. @@ -852,6 +855,7 @@ If the target cannot be achieved, only one card is returned with the score set a + Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, and we may use it for something else in the future. If you think you need it, let us know! @@ -877,12 +881,13 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN -struct ddTableResults * tablepstruct ddTableResults * tablep +struct ddTableResults \* tablepstruct ddTableResults \* tablep + CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ *tablep” , which must be declared before calling CalcDDtable. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. @@ -892,7 +897,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + @@ -901,16 +906,17 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + - +
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealspstruct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint modeint trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *respstruct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults *prespstruct allParResults *prespstruct allParResults \*prespstruct allParResults \*presp
+ 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. +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. 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. @@ -951,21 +957,22 @@ The maximum number of DD tables in a CallAllTables call depends on the number of -struct boards *bopstruct boards *bopstruct boardsPBN *bop +struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop -struct solvedBoards * solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp +struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp int chunkSizeint chunkSize + `SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. `SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. -The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. +The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. It is important to understand the parallelism and the concept of a chunk. @@ -985,10 +992,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResults *prespstruct parResultsDealer *presp +struct parResults \*prespstruct parResultsDealer \*presp int vulnerableint dealer @@ -1003,10 +1010,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or Sidespar  -struct ddTableResults *tablep  +struct ddTableResults \*tablep  -struct parResultsDealer *sidesRes[2]  +struct parResultsDealer \*sidesRes[2]  int vulnerable  @@ -1018,10 +1025,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or DealerParBinSidesParBin -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults \*tablepstruct ddTableResults \*tablep -struct parResultsMaster * prespstruct parResultsMaster * presp +struct parResultsMaster \* prespstruct parResultsMaster \* presp int vulnerableint dealer @@ -1036,13 +1043,14 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or ConvertToDealerTextForamatConvertToSidesTextFormat -struct parResultsMaster *presstruct parResultsMaster *pres +struct parResultsMaster \*presstruct parResultsMaster \*pres -char *respstruct parTextResults *resp +char \*respstruct parTextResults \*resp + The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. @@ -1061,8 +1069,7 @@ There may be several par contracts, for instance 3NT just making and 5C just mak Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. * “NS:NS 23S,N 23H”: Only North makes 3 hearts. * “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. @@ -1070,7 +1077,7 @@ DealerPar() and SidesPar() give each par contract as a separate text string: * “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. * “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. * SidesPar() give the par contract text strings as described above for each side. DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. @@ -1100,7 +1107,7 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding. struct playTraceBin playstruct playTracePBN playPBN -struct solvedPlay *solvedpstruct solvedPlay *solvedp +struct solvedPlay \*solvedpstruct solvedPlay \*solvedp int thrIdint thrId @@ -1126,22 +1133,23 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one -struct boards *bopstruct boardsPBN *bopPBN +struct boards \*bopstruct boardsPBN \*bopPBN -struct playTracesBin *plpstruct playTracesPBN *plpPBN +struct playTracesBin \*plpstruct playTracesPBN \*plpPBN -struct solvedPlays *solvedpstruct solvedPlays *solvedp +struct solvedPlays \*solvedpstruct solvedPlays \*solvedp int chunkSizeint chunkSize + AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. -The AnalyseAllPlays* 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. +The AnalyseAllPlays\* 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. Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. @@ -1157,6 +1165,7 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi + SetMaxThreads returns the actual number of threads. 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 threads than there are processor cores, as this will only require more memory and will not improve performance. Within these constraints, DDS auto-configures the @@ -1174,7 +1183,8 @@ SetMaxThreads can be called multiple times even within the same session. So it i It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. -=== Return codes +## Return codes + @@ -1237,7 +1247,7 @@ different number of boards in its first two arguments. - @@ -1252,13 +1262,13 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + - + - +
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables*(), returned when the denomination filter vector has no entries.-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables*(), returned when too many tables are requested.-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks*(), returned when the chunk size is < 1.-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
From 51d860b48d131f865b50cd2712fa0142c3288fb2 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 21:21:16 +0100 Subject: [PATCH 171/199] Extra commit before copying the file --- dds.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dds.md b/dds.md index 32bef118..452d2ca3 100644 --- a/dds.md +++ b/dds.md @@ -22,7 +22,7 @@ The double dummy trick values for all 5 \* 4 = 20 possible combinations of a han To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. From e2b3bbeec4cf0741af82601865cff8facad0967f Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 21:21:16 +0100 Subject: [PATCH 172/199] Extra commit before copying the file --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 32bef118..452d2ca3 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -22,7 +22,7 @@ The double dummy trick values for all 5 \* 4 = 20 possible combinations of a han To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBorads`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. +Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. From 99ddd78689dd3beb75f16ea8e3a0bb31d7e5be0d Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 22:14:02 +0100 Subject: [PATCH 173/199] Re-removed dds.md --- dds.md | 1358 -------------------------------------------------------- 1 file changed, 1358 deletions(-) delete mode 100644 dds.md diff --git a/dds.md b/dds.md deleted file mode 100644 index 452d2ca3..00000000 --- a/dds.md +++ /dev/null @@ -1,1358 +0,0 @@ -Bo Haglund, Soren Hein, Bob Richardson - -Rev X, 2014-11-16 - -Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ - -# Description of the DLL functions supported in Double Dummy Problem Solver 2.8 -## Callable functions -The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. - -Return codes are given at the end. - -Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! - -## The Basic Functions - -The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. - -### The Multi-Thread Double Dummy Solver Functions - -The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. - -To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. - -Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions `SolveAllBoards`, `SolveAllChunksBin` and `SolveAllChunksPBN`. The hands are then solved in parallel using the available threads. - -The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling `SetMaxThreads`. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration. - -Calling `FreeMemory` causes DDS to give up its dynamically allocated memory. - -### The PAR Calculation Functions - -The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract. - -Two alternatives are given: - -1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. -2. The dealer hand is assumed to “start the bidding”. - -The presentation of the par score and contracts are given in alternative formats. - -The functions `Par`, `SidesPar` and `DealerPar` do the par calculation; their call must be preceded by a function call calculating the double dummy table values. - -The functions `SidesParBin` and `DealerParBin` provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, `ConvertToSidesTextFormat` and `ConvertToDealerTextFormat`, are included as examples. - -It is possible as an option to perform par calculation in `CalcAllTables` and `CalcAllTablesPBN`. - -The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration. - -### Double Dummy Value Analyser Functions - -The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionArgumentsFormatComment
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int solutions
int mode
struct futureTricks \*futp
int threadIndex
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes \*resp
struct allParResults \*pres
 
SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards \*solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
int chunkSize
 
Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults \*presp
int vulnerable
 
DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge -of the dealer.
struct parResultsDealer \*presp
int dealer
int vulnerable
 
DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster \* presp
int dealer
int vulnerable
 
ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.
char \*resp
 
SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer \*presp
int vulnerable
 
SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
int vulnerable
 
ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.
char \*resp
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTableResults \*tablep
struct parResults \*presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults \*tablep
int vulnerable
struct parResults \*presp
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
struct solvedPlay \*solvedp
int thrId
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
struct solvedPlay \*solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin \*plp
struct solvedPlays \*solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN \*plpPBN
struct solvedPlays \*solvedp
int chunkSize
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
ErrorMessageint code Turns a return code into an error message string.
-
- -## Data structure -Common encodings are as follows - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
StructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
StructFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
StructFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
StructFieldComment
parTextResultschar parText[2][128];
int equal;
StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
StructFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
StructFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
StructFieldComment
solvedPlayint number;
int tricks[53];Starting position and up to 52 cards
StructFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- -## Functions - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SolveBoardSolveoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
- -SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. - -SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. - -If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. - -SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. - -There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. - -The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. - -For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
targetsolutionscomment
-11Find the maximum number of tricks for the side to -play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to -play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with -score set to 0.
02Return all cards that legal to play, with score set to -0.
1 .. 131If score is -1: Target cannot be reached.
-If score is 0: In fact no tricks at all can be won.
-If score is > 0: score will always equal target, even if more tricks can be won.
-One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
-If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
- -Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, -and we may use it for something else in the future. If you think you need it, let us know! - -“Reuse” means “reuse the transposition table from the previous run with the same thread number”. -For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. - -1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` - -2nd call, South leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2` - -3rd call, West leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3` - -4th call, North leads: `SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0` - - - - - - - - - - - - - - - -
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablep
- -CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. - - - - - - - - - - - - - - - - - - - - - - - - -
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults \*prespstruct allParResults \*presp
- -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. - -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: - - - - - - - - - - - - - - - - - - - - - - - - -
Number of strainsMaximum number of DD tables
532
440
353
280
1160
- - - - - - - - - - - - - - - - - - -
SolveAllBoardsSolverAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp
int chunkSizeint chunkSize
- -`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. - -`SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. - -The SolveAll\* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call. - -It is important to understand the parallelism and the concept of a chunk. - -If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. - -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. - -No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. - -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! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResults \*prespstruct parResultsDealer \*presp
int vulnerableint dealer
 int vulnerable
 
Sidespar 
struct ddTableResults \*tablep 
struct parResultsDealer \*sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResultsMaster \* prespstruct parResultsMaster \* presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
char \*respstruct parTextResults \*resp
- -The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. - -Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. - -The `vulnerable` parameter is given using Vulnerable encoding. - -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. - -The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. - -The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). - -In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. - -There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. - -Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: - -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. -* “NS:NS 23S,N 23H”: Only North makes 3 hearts. -* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. - -DealerPar() and SidesPar() give each par contract as a separate text string: - -* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. -* “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. -* SidesPar() give the par contract text strings as described above for each side. - -DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. - -After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. -Output example from ConvertToDealerTextFormat: - -“Par 110: NS 2S NS 2H” - -Output examples from ConvertToSidesTextFormat: - -“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT
-EW Par 120: W 1NT+1” when it matters who starts the bidding. - - - - - - - - - - - - - - - - - - - - - -
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedp
int thrIdint thrId
- -AnalysePlayPBN is just like AnalysePlayBin, except for the input format. - -The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. - -As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: - -9 10 10 10 10 9 9 - -The number of tricks are always seen from declarer’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. - - - - - - - - - - - - - - - - - - - - - -
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedp
int chunkSizeint chunkSize
- -AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. - -The AnalyseAllPlays\* 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. - -Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. - - - - - - - - - - - - -
SetMaxThreadsFreeMemory
int userThreadsvoid
- -SetMaxThreads returns the actual number of threads. - -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 threads 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. - -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. - -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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory. - -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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own. - -It may be possible, 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. - -SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. - -It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. - -## Return codes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a -different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) -Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Revision History
Rev A2006-02-25First issue
Rev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. -Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, -AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, -ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From 1956d87d8e879f325a6acce56950920b9ac7ef62 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Sun, 21 Dec 2014 23:16:59 +0100 Subject: [PATCH 174/199] Added anchors --- doc/dll-description.md | 113 +++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 452d2ca3..75df8cbc 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play int target @@ -77,7 +77,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. +SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. int target @@ -96,21 +96,21 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) +CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) struct ddTableResults \* tablep   -CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. +CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. struct ddTableResults \* tablep   -CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded. +CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded. int mode @@ -126,7 +126,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format. +CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format. int mode @@ -142,14 +142,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”! +SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”! struct solvedBoards \*solvedp   -SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded. struct solvedBoards \*solvedp @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use! struct solvedBoards \*solvedp @@ -169,7 +169,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded. struct solvedBoards \*solvedp @@ -179,7 +179,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table. +Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table. struct parResults \*presp @@ -189,7 +189,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal   -DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer. @@ -203,7 +203,7 @@ of the dealer.   -DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output. +DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output. struct parResultsMaster \* presp @@ -216,14 +216,14 @@ of the dealer.   -ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin. +ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin. char \*resp   -SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format. +SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format. struct parResultsDealer \*presp @@ -233,7 +233,7 @@ of the dealer.   -SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output. +SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output. struct parResultsMaster sidesRes[2] @@ -243,14 +243,14 @@ of the dealer.   -ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin. +ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin. char \*resp   -CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! int vulnerable @@ -263,7 +263,7 @@ of the dealer.   -CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! struct ddTableResults \*tablep @@ -276,7 +276,7 @@ of the dealer.   -AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. struct playTraceBin play @@ -289,7 +289,7 @@ of the dealer.   -AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. struct playTracePBN playPBN @@ -302,7 +302,7 @@ of the dealer.   -AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. +AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. struct playTracesBin \*plp @@ -315,7 +315,7 @@ of the dealer.   -AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. +AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. struct playTracesPBN \*plpPBN @@ -328,15 +328,15 @@ of the dealer.   -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)   -FreeMemoryvoid Frees DDS allocated dynamical memory. +FreeMemoryvoid Frees DDS allocated dynamical memory.   -ErrorMessageint code Turns a return code into an error message string. +ErrorMessageint code Turns a return code into an error message string. @@ -354,7 +354,7 @@ Common encodings are as follows -SuitSpades0 +SuitSpades0 Hearts1 @@ -368,7 +368,7 @@ Common encodings are as follows NT4   -HandNorth0 +HandNorth0 East1 @@ -379,12 +379,12 @@ Common encodings are as follows West3   -SideN-S0 +SideN-S0 E-W1   -CardBit 2Rank of deuce +CardBit 2Rank of deuce ...  @@ -395,13 +395,14 @@ Common encodings are as follows Bit 14Rank of ace   -HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero. +HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.   -PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K +PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K + @@ -410,7 +411,7 @@ Common encodings are as follows - + @@ -431,7 +432,7 @@ Common encodings are as follows - + @@ -453,7 +454,7 @@ Common encodings are as follows - + @@ -463,7 +464,7 @@ Common encodings are as follows - + @@ -476,7 +477,7 @@ Common encodings are as follows - + @@ -489,7 +490,7 @@ Common encodings are as follows - + @@ -511,7 +512,7 @@ Common encodings are as follows - + @@ -532,7 +533,7 @@ Common encodings are as follows - + @@ -557,7 +558,7 @@ Common encodings are as follows - + @@ -570,7 +571,7 @@ Common encodings are as follows - + @@ -580,7 +581,7 @@ Common encodings are as follows - + @@ -593,7 +594,7 @@ Common encodings are as follows - + @@ -606,7 +607,7 @@ Common encodings are as follows - + @@ -616,7 +617,7 @@ Common encodings are as follows - + @@ -632,7 +633,7 @@ Common encodings are as follows - + @@ -648,7 +649,7 @@ Common encodings are as follows - + @@ -670,7 +671,7 @@ Common encodings are as follows - + @@ -683,7 +684,7 @@ Common encodings are as follows - + @@ -699,7 +700,7 @@ Common encodings are as follows - + @@ -712,7 +713,7 @@ Common encodings are as follows - + @@ -725,7 +726,7 @@ Common encodings are as follows - + @@ -738,7 +739,7 @@ Common encodings are as follows - + @@ -751,7 +752,7 @@ Common encodings are as follows - + @@ -764,7 +765,7 @@ Common encodings are as follows
dealint trump;Suit encodingdealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.structFieldComment
dealPBNint trump;Suit encodingdealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. HoldingddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLESddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINSstructFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structureddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];structFieldComment
boardsint noOfBoards;Number of boardsboardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];structFieldComment
boardsPBNint noOfBoards;Number of boardsboardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.structFieldComment
solvedBoardsint noOfBoards;solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLESddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINSStructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD tableallParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;parResultsDealerint number;
int score;StructFieldComment
parResultsMasterint score;parResultsMasterint score;
int number;StructFieldComment
contractTypeint underTricks;contractTypeint underTricks;
int overTricks;StructFieldComment
parTextResultschar parText[2][128];parTextResultschar parText[2][128];
int equal;StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.StructFieldComment
playTracesBinint noOfBoards;playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];StructFieldComment
playTracesPBNint noOfBoards;playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];StructFieldComment
solvedPlayint number;solvedPlayint number;
int tricks[53];Starting position and up to 52 cardsStructFieldComment
solvedPlaysint noOfBoards;solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- + From 6241b3f4f00bc55ef9956c580b3c874d8317f409 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 01:03:04 +0100 Subject: [PATCH 175/199] Moved the anchors to the explanatory section --- doc/dll-description.md | 106 ++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 39 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 75df8cbc..d886dbce 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -8,7 +8,7 @@ Latest DLL issue with this description is available at http://www.bahnhof.se/wb7 ## Callable functions The callable functions are all preceded with `extern "C" __declspec(dllimport) int __stdcall`. The prototypes are available in `dll.h`, in the include directory. -Return codes are given at the end. +[Return codes](#ReturnCodes) are given at the end. Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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! @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -77,7 +77,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -96,21 +96,21 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -126,7 +126,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -142,14 +142,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -169,7 +169,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -179,7 +179,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -189,7 +189,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - @@ -203,7 +203,7 @@ of the dealer. - + @@ -216,14 +216,14 @@ of the dealer. - + - + @@ -233,7 +233,7 @@ of the dealer. - + @@ -243,14 +243,14 @@ of the dealer. - + - + @@ -263,7 +263,7 @@ of the dealer. - + @@ -276,7 +276,7 @@ of the dealer. - + @@ -289,7 +289,7 @@ of the dealer. - + @@ -302,7 +302,7 @@ of the dealer. - + @@ -315,7 +315,7 @@ of the dealer. - + @@ -328,15 +328,15 @@ of the dealer. - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1312,75 +1312,75 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - - +
SolveBoardSolveoardPBNSolveBoardSolveBoardPBN
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play[SolveBoard](#SolveBoard)struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.[SolveBoardPBN](#SolveBoardPBN)struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)[CalcDDtable](#CalcDDtable)struct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults \* tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.[CalcDDtablePBN](#CalcDDtablePBN)struct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults \* tablep
 
CalcAllTablesstruct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.[CalcAllTables](#CalcAllTables)struct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
 
CalcAllTablesPBNstruct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.[CalcAllTablesPBN](#CalcAllTablesPBN)struct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
 
SolveAllBoardsstruct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”![SolveAllBoards](#SolveAllBoards)struct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards \*solvedp
 
SolveAllChunksBinstruct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.[SolveAllChunksBin](#SolveAllChunksBin)struct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
 
SolveAllChunksstruct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use![SolveAllChunks](#SolveAllChunks)struct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards \*solvedp
 
SolveAllChunksPBNstruct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.[SolveAllChunksPBN](#SolveAllChunksPBN)struct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedp
 
Parstruct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.[Par](#Par)struct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults \*presp
 
DealerParstruct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge +[DealerPar](#DealerPar)struct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
 
DealerParBinstruct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.[DealerParBin](#DealerParBin)struct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster \* presp
 
ConvertToDealerTextFormatstruct parResultsMaster \*presTextExample of text output from DealerParBin.[ConvertToDealerTextFormat](#ConvertToDealerTextFormat)struct parResultsMaster \*presTextExample of text output from DealerParBin.
char \*resp
 
SidesParstruct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.[SidesPar](#SidesPar)struct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer \*presp
 
SidesParBinstruct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.[SidesParBin](#SidesParBin)struct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
 
ConvertToSidesTextFormatstruct parResultsMaster \*presTextExample of text output from SidesParBin.[ConvertToSidesTextFormat](#ConvertToSidesTextFormat)struct parResultsMaster \*presTextExample of text output from SidesParBin.
char \*resp
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead![CalcPar](#CalcPar)struct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead![CalcParPBN](#CalcParPBN)struct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults \*tablep
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.[AnalysePlayBin](#AnalysePlayBin)struct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.[AnalysePlayPBN](#AnalysePlayPBN)struct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
 
AnalyseAllPlaysBinstruct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.[AnalyseAllPlaysBin](#AnalyseAllPlaysBin)struct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin \*plp
 
AnalyseAllPlaysPBNstruct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.[AnalyseAllPlaysPBN](#AnalyseAllPlaysPBN)struct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN \*plpPBN
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)[SetMaxThreads](#SetMaxThreads)int userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
FreeMemoryvoid Frees DDS allocated dynamical memory.[FreeMemory](#FreeMemory)void Frees DDS allocated dynamical memory.
 
ErrorMessageint code Turns a return code into an error message string.[ErrorMessage](#ErrorMessage)int code Turns a return code into an error message string.
@@ -765,7 +765,7 @@ Common encodings are as follows - + @@ -874,7 +874,7 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure
SolveBoardSolveBoardPBNSolveBoardSolveBoardPBN
- + @@ -893,7 +893,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy
CalcDDtableCalcDDtablePBNCalcDDtableCalcDDtablePBN
- + @@ -953,7 +953,7 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
CalcAllTablesCalcAllTablesPBNCalcAllTablesCalcAllTablesPBN
- + @@ -988,7 +988,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or
SolveAllBoardsSolverAllChunksBinSolveAllChunksPBNSolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
- + @@ -1008,7 +1008,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + @@ -1023,7 +1023,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + @@ -1041,7 +1041,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + @@ -1097,7 +1097,35 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding.
ParDealerParParDealerPar
 
Sidespar SidesPar 
struct ddTableResults \*tablep  
DealerParBinSidesParBinDealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep 
ConvertToDealerTextForamatConvertToSidesTextFormatConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
- + + + + + + + + + + + + + + + + + +
AnalysePlayBinAnalysePlayPBNCalcParCalcParPBN
struct ddTableDeal dlstruct ddTableDealPBN dlN
int vulnerablestruct ddTableResults * tp
struct ddTableResults * tpint vulnerable
struct parResults *prespstruct parResults *presp
+ +CalcParPBN is just like CalcPar, except for the input format. + +Each of these functions calculates both the double-dummy table solution and the par solution to a given deal. + +Both functions are deprecated. Instead use one of the CalcDDtable functions followed by Par(). + + + + + @@ -1129,7 +1157,7 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one
AnalysePlayBinAnalysePlayPBN
- + @@ -1157,7 +1185,7 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi
AnalyseAllPlaysBinAnalyseAllPlaysPBNAnalyseAllPlaysBinAnalyseAllPlaysPBN
- + @@ -1183,7 +1211,7 @@ It may be possible, especially on non-Windows systems, to call SetMaxThreads() a SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically. It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. - + ## Return codes
SetMaxThreadsFreeMemorySetMaxThreadsFreeMemory
From a2e721d99bf1a735998debfb6c292681a347ceaa Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 01:33:24 +0100 Subject: [PATCH 176/199] Added most of the links --- doc/dll-description.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index d886dbce..faa11a60 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -343,7 +343,7 @@ of the dealer.
-## Data structure +## Data structures Common encodings are as follows @@ -1310,7 +1310,7 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + From 4c5f77d92fa90029155064ae25336c1fa051bfe8 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 01:34:29 +0100 Subject: [PATCH 177/199] Added most of the links --- doc/dll-description.md | 102 ++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index faa11a60..562db9bd 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,7 +59,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -71,13 +71,13 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + @@ -89,28 +89,28 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + @@ -119,14 +119,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + @@ -135,65 +135,65 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - - + @@ -203,10 +203,10 @@ of the dealer. - + - + @@ -216,83 +216,83 @@ of the dealer. - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -302,26 +302,26 @@ of the dealer. - + - + - + - + - + - + From a75d6bde3fbba117a433b6eb9fc7c5a49ed5deeb Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 02:49:27 +0100 Subject: [PATCH 178/199] Redid links because Github doesn't do markdoen inside html tags --- doc/dll-description.md | 168 ++++++++++++++++++++--------------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 562db9bd..dc29c498 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,284 +59,284 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -336,10 +336,9 @@ of the dealer. - + -
Rev A2006-02-25First issueRev A2006-02-25First issue
Rev B2006-03-20Updated issue
[SolveBoard](#SolveBoard)struct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play[SolveBoard](#SolveBoard)struct [deal](#deal) dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int targetint mode
struct futureTricks \*futpstruct [futureTricks](#futureTricks) \*futp
int threadIndex
 
[SolveBoardPBN](#SolveBoardPBN)struct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.[SolveBoardPBN](#SolveBoardPBN)struct [dealPBN](#dealPBN) dlPBNPBNAs SolveBoard, but with PBN deal format.
int targetint mode
struct futureTricks \*futpstruct [futureTricks](#futureTricks) \*futp
int threadIndex
 
[CalcDDtable](#CalcDDtable)struct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)[CalcDDtable](#CalcDDtable)struct [ddTableDeal](#ddTableDeal) tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults \* tablepstruct [ddTableResults](#ddTableResults) \* tablep
 
[CalcDDtablePBN](#CalcDDtablePBN)struct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.[CalcDDtablePBN](#CalcDDtablePBN)struct [ddTableDealPBN](#ddTableDealPBN) tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults \* tablepstruct [ddTableResults](#ddTableResults) \* tablep
 
[CalcAllTables](#CalcAllTables)struct ddTableDeals \*dealspBinarySolves a number of hands in parallel. Multi-threaded.[CalcAllTables](#CalcAllTables)struct [ddTableDeals](#ddTableDeals) \*dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint trumpFilter[5]
struct ddTablesRes \*respstruct [ddTablesRes](#ddtablesRes) \*resp
struct allParResults \*presstruct [allParResults](#allParResults) \*pres
 
[CalcAllTablesPBN](#CalcAllTablesPBN)struct ddTableDealsPBN \*dealspPBNAs CalcAllTables, but with PBN deal format.[CalcAllTablesPBN](#CalcAllTablesPBN)struct [ddTableDealsPBN](#ddTableDealsPBN) \*dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint trumpFilter[5]
struct ddTablesRes \*respstruct [ddTablesRes](#ddTablesRes) \*resp
struct allParResults \*presstruct [allParResults](#allParResults) \*pres
 
[SolveAllBoards](#SolveAllBoards)struct boardsPBN \*bopPBNConsider using this instead of the next 3 “Chunk” functions”![SolveAllBoards](#SolveAllBoards)struct [boardsPBN](#boardsPBN) \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards \*solvedpstruct [solvedBoards](#solvedBoards) \*solvedp
 
[SolveAllChunksBin](#SolveAllChunksBin)struct boards \*bopBinarySolves a number of hands in parallel. Multi-threaded.[SolveAllChunksBin](#SolveAllChunksBin)struct [boards](#boards) \*bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedpstruct [solvedBoards](#solvedBoards) \*solvedp
int chunkSize
 
[SolveAllChunks](#SolveAllChunks)struct boardsPBN \*bopPBNAlias for SolveAllChunksPBN; don’t use![SolveAllChunks](#SolveAllChunks)struct [boardsPBN](#boardsPBN) \*bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards \*solvedpstruct [solvedBoards](#solvedBoards) \*solvedp
int chunkSize
 
[SolveAllChunksPBN](#SolveAllChunksPBN)struct boardsPBN \*bopPBNSolves a number of hands in parallel. Multi-threaded.[SolveAllChunksPBN](#SolveAllChunksPBN)struct [boardsPBN](#boardsPBN) \*bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards \*solvedpstruct [solvedBoards](#solvedBoards) \*solvedp
int chunkSize
 
[Par](#Par)struct ddTableResults \*tablepNo formatSolves for the par contracts given a DD result table.[Par](#Par)struct [ddTableResults](#ddTableResults) \*tablepNo formatSolves for the par contracts given a DD result table.
struct parResults \*prespstruct [parResults](#parResults) \*presp
int vulnerable
 
[DealerPar](#DealerPar)struct ddTableResults \*tablepNo formatSimilar to Par(), but requires and uses knowledge +[DealerPar](#DealerPar)struct [ddTableResults](#ddTableResults) \*tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer \*prespstruct [parResultsDealer](#parResultsDealer) \*presp
int dealer
 
[DealerParBin](#DealerParBin)struct ddTableResults \*tablepBinarySimilar to DealerPar, but with binary output.[DealerParBin](#DealerParBin)struct [ddTableResults](#ddTableResults) \*tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster \* prespstruct [parResultsMaster](#parResultsMaster) \* presp
int dealer
 
[ConvertToDealerTextFormat](#ConvertToDealerTextFormat)struct parResultsMaster \*presTextExample of text output from DealerParBin.[ConvertToDealerTextFormat](#ConvertToDealerTextFormat)struct [parResultsMaster](#parResultsMaster) \*presTextExample of text output from DealerParBin.
char \*resp
 
[SidesPar](#SidesPar)struct ddTableResults \*tablepNo formatPar results are given for sides with the DealerPar output format.[SidesPar](#SidesPar)struct [ddTableResults](#ddTableResults) \*tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer \*prespstruct [parResultsDealer](#parResultsDealer) \*presp
int vulnerable
 
[SidesParBin](#SidesParBin)struct ddTableResults \*tablepBinarySimilar to SidesPar, but with binary output.[SidesParBin](#SidesParBin)struct [ddTableResults](#ddTableResults) \*tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]struct [parResultsMaster](#parResultsMaster) sidesRes[2]
int vulnerable
 
[ConvertToSidesTextFormat](#ConvertToSidesTextFormat)struct parResultsMaster \*presTextExample of text output from SidesParBin.[ConvertToSidesTextFormat](#ConvertToSidesTextFormat)struct [parResultsMaster](#parResultsMaster) \*presTextExample of text output from SidesParBin.
char \*resp
 
[CalcPar](#CalcPar)struct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead![CalcPar](#CalcPar)struct [ddTableDeal](#ddTableDeal) tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTableResults \*tablepstruct [ddTableResults](#ddTabeleResults) \*tablep
struct parResults \*prespstruct [parResults](#parResults) \*presp
 
[CalcParPBN](#CalcParPBN)struct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead![CalcParPBN](#CalcParPBN)struct [ddTableDealPBN](#ddTableDealPBN) tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults \*tablepstruct [ddTableResult](#ddTableResults)s \*tablep
int vulnerable
struct parResults \*prespstruct [parResults](#parResults) \*presp
 
[AnalysePlayBin](#AnalysePlayBin)struct deal dlBinaryReturns the par result after each card in a particular play sequence.[AnalysePlayBin](#AnalysePlayBin)struct [deal](#deal) dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin playstruct [playTraceBin](#playTraceBin) play
struct solvedPlay \*solvedpstruct [solvedPlay](#solvedPlay) \*solvedp
int thrId
 
[AnalysePlayPBN](#AnalysePlayPBN)struct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.[AnalysePlayPBN](#AnalysePlayPBN)struct [dealPBN](#dealPBN) dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBNstruct [playTracePBN](#playTracePBN) playPBN
struct solvedPlay \*solvedp
 
[AnalyseAllPlaysBin](#AnalyseAllPlaysBin)struct boards \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.[AnalyseAllPlaysBin](#AnalyseAllPlaysBin)struct [boards](#boards) \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin \*plpstruct [playTracesBi](#playTracesBin)n \*plp
struct solvedPlays \*solvedpstruct [solvedPlays](#solvedPlays) \*solvedp
int chunkSize
 
[AnalyseAllPlaysPBN](#AnalyseAllPlaysPBN)struct boardsPBN \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.[AnalyseAllPlaysPBN](#AnalyseAllPlaysPBN)struct [boardsPBN](#boardsPBN) \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN \*plpPBNstruct [playTracesPBN](#playTracesPBN) \*plpPBN
struct solvedPlays \*solvedpstruct [solvedPlay](#solvedPlay)s \*solvedp
int chunkSize
[SolveBoard](#SolveBoard)struct [deal](#deal) dlBinaryThe most basic function, solves a single hand from the beginning or from later playSolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int targetint target
int solutionsint solutions
int modeint mode
struct [futureTricks](#futureTricks) \*futpstruct futureTricks *futp
int threadIndex
 
[SolveBoardPBN](#SolveBoardPBN)struct [dealPBN](#dealPBN) dlPBNPBNAs SolveBoard, but with PBN deal format.SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int targetint target
int solutionsint solutions
int modeint mode
struct [futureTricks](#futureTricks) \*futpstruct futureTricks *futp
int threadIndexint threadIndex
 
[CalcDDtable](#CalcDDtable)struct [ddTableDeal](#ddTableDeal) tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct [ddTableResults](#ddTableResults) \* tablepstruct ddTableResults * tablep
 
[CalcDDtablePBN](#CalcDDtablePBN)struct [ddTableDealPBN](#ddTableDealPBN) tableDealPBNPBNAs CalcDDtable, but with PBN deal format.CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct [ddTableResults](#ddTableResults) \* tablepstruct ddTableResults * tablep
 
[CalcAllTables](#CalcAllTables)struct [ddTableDeals](#ddTableDeals) \*dealspBinarySolves a number of hands in parallel. Multi-threaded.CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct [ddTablesRes](#ddtablesRes) \*respstruct ddtablesRes *resp
struct [allParResults](#allParResults) \*presstruct allParResultsa> *pres
 
[CalcAllTablesPBN](#CalcAllTablesPBN)struct [ddTableDealsPBN](#ddTableDealsPBN) \*dealspPBNAs CalcAllTables, but with PBN deal format.CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct [ddTablesRes](#ddTablesRes) \*respstruct ddTablesRes *resp
struct [allParResults](#allParResults) \*presstruct allParResults *pres
 
[SolveAllBoards](#SolveAllBoards)struct [boardsPBN](#boardsPBN) \*bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct [solvedBoards](#solvedBoards) \*solvedpstruct solvedBoards *solvedp
 
[SolveAllChunksBin](#SolveAllChunksBin)struct [boards](#boards) \*bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct [solvedBoards](#solvedBoards) \*solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
 
[SolveAllChunks](#SolveAllChunks)struct [boardsPBN](#boardsPBN) \*bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct [solvedBoards](#solvedBoards) \*solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
 
[SolveAllChunksPBN](#SolveAllChunksPBN)struct [boardsPBN](#boardsPBN) \*bopPBNSolves a number of hands in parallel. Multi-threaded.SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct [solvedBoards](#solvedBoards) \*solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
 
[Par](#Par)struct [ddTableResults](#ddTableResults) \*tablepNo formatSolves for the par contracts given a DD result table.Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.
struct [parResults](#parResults) \*prespstruct parResults *presp
int vulnerableint vulnerable
 
[DealerPar](#DealerPar)struct [ddTableResults](#ddTableResults) \*tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct [parResultsDealer](#parResultsDealer) \*prespstruct parResultsDealer *presp
int dealerint dealer
int vulnerableint vulnerable
 
[DealerParBin](#DealerParBin)struct [ddTableResults](#ddTableResults) \*tablepBinarySimilar to DealerPar, but with binary output.DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.
struct [parResultsMaster](#parResultsMaster) \* prespstruct parResultsMaster * presp
int dealerint dealer
int vulnerableint vulnerable
 
[ConvertToDealerTextFormat](#ConvertToDealerTextFormat)struct [parResultsMaster](#parResultsMaster) \*presTextExample of text output from DealerParBin.ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.
char \*respchar *resp
 
[SidesPar](#SidesPar)struct [ddTableResults](#ddTableResults) \*tablepNo formatPar results are given for sides with the DealerPar output format.SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.
struct [parResultsDealer](#parResultsDealer) \*prespstruct parResultsDealer *presp
int vulnerableint vulnerable
 
[SidesParBin](#SidesParBin)struct [ddTableResults](#ddTableResults) \*tablepBinarySimilar to SidesPar, but with binary output.SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.
struct [parResultsMaster](#parResultsMaster) sidesRes[2]struct parResultsMaster sidesRes[2]
int vulnerableint vulnerable
 
[ConvertToSidesTextFormat](#ConvertToSidesTextFormat)struct [parResultsMaster](#parResultsMaster) \*presTextExample of text output from SidesParBin.ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.
char \*respchar *resp
 
[CalcPar](#CalcPar)struct [ddTableDeal](#ddTableDeal) tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerableint vulnerable
struct [ddTableResults](#ddTabeleResults) \*tablepstruct ddTabeleResults *tablep
struct [parResults](#parResults) \*prespstruct parResults *presp
 
[CalcParPBN](#CalcParPBN)struct [ddTableDealPBN](#ddTableDealPBN) tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct [ddTableResult](#ddTableResults)s \*tablepstruct ddTableResults *tablep
int vulnerableint vulnerable
struct [parResults](#parResults) \*prespstruct parResults *presp
 
[AnalysePlayBin](#AnalysePlayBin)struct [deal](#deal) dlBinaryReturns the par result after each card in a particular play sequence.AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct [playTraceBin](#playTraceBin) playstruct playTraceBin play
struct [solvedPlay](#solvedPlay) \*solvedpstruct solvedPlay *solvedp
int thrIdint thrId
 
[AnalysePlayPBN](#AnalysePlayPBN)struct [dealPBN](#dealPBN) dlPBNPBNAs AnalysePlayBin, but with PBN deal format.AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct [playTracePBN](#playTracePBN) playPBNstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay *solvedp
int thrIdint thrId
 
[AnalyseAllPlaysBin](#AnalyseAllPlaysBin)struct [boards](#boards) \*bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct [playTracesBi](#playTracesBin)n \*plpstruct playTracesBin *plp
struct [solvedPlays](#solvedPlays) \*solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
 
[AnalyseAllPlaysPBN](#AnalyseAllPlaysPBN)struct [boardsPBN](#boardsPBN) \*bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct [playTracesPBN](#playTracesPBN) \*plpPBNstruct playTracesPBN *plpPBN
struct [solvedPlay](#solvedPlay)s \*solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
 
[SetMaxThreads](#SetMaxThreads)int userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
[FreeMemory](#FreeMemory)void Frees DDS allocated dynamical memory.FreeMemoryvoid Frees DDS allocated dynamical memory.
 
[ErrorMessage](#ErrorMessage)int code Turns a return code into an error message string.ErrorMessageint code Turns a return code into an error message string.
From eb9f161317c1208a5fd4201b1fc1c02187bfa0d9 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 03:01:23 +0100 Subject: [PATCH 179/199] Three minor bugs --- doc/dll-description.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index dc29c498..36baf4f0 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -96,7 +96,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablep
 
ErrorMessageint code Turns a return code into an error message string.ErrorMessageint code Turns a return code into an error message string.
From b0226263d6f9970d914eb8d5bd94d385bc1cfb73 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 04:20:11 +0100 Subject: [PATCH 180/199] Playing with non-bring-spaces --- doc/dll-description.md | 70 +++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 36baf4f0..5b179402 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,40 +59,40 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later playSolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int targetint target
int solutionsint solutions
int modeint mode
struct futureTricks *futpstruct futureTricks *futp
int threadIndex
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int targetint target
int solutionsint solutions
int modeint mode
struct futureTricks *futpstruct futureTricks *futp
int threadIndexint threadIndex
 
Rev A2006-02-25First issue
Rev B2006-03-20Updated issueRev B2006-03-20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to playRev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parametersRev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutionsRev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRankRev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread supportRev I2010-04-10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar dealsRev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer handRev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBNRev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. +Rev M2012-07-06Added SolveAllBoards. Rev N, 2012-07-16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBNRev P2013-03-16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBNRev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBNRev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBNRev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunksRev T2014-03-01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
From a5215d2d52520cdd9bf21540bbfb172de5380bc3 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 04:37:26 +0100 Subject: [PATCH 181/199] Trying with inline css --- doc/dll-description.md | 141 ++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 71 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 5b179402..88bb62a2 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -54,7 +54,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -73,7 +73,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -96,239 +96,239 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -336,7 +336,6 @@ of the dealer. - From a3d884358b53f7f5c5bb6cce5c3fa461ce4efc32 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 04:39:51 +0100 Subject: [PATCH 182/199] Oops, trying with white-space:nowrap; --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 88bb62a2..2a30f35b 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -54,7 +54,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal
FunctionArgumentsFormatCommentFunctionArgumentsFormatComment
struct futureTricks *futp
int threadIndex
int threadIndex
 
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults * tablepstruct ddTableResults *tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults * tablepstruct ddTableResults *tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddtablesRes *respstruct ddtablesRes *resp
struct allParResultsa> *presstruct allParResultsa> *pres
 
CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.CalcAllTablesPBNstruct  ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *resp
struct allParResults *presstruct allParResults *pres
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedpstruct solvedBoards *solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded.SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSize
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *prespstruct parResults *presp
int vulnerableint vulnerable
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *prespstruct parResultsDealer *presp
int dealerint dealer
int vulnerableint vulnerable
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster * prespstruct parResultsMaster *presp
int dealerint dealer
int vulnerableint vulnerable
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.
char *respchar *resp
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *prespstruct parResultsDealer *presp
int vulnerableint vulnerable
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]struct parResultsMaster sidesRes[2]
int vulnerable
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.
char *respchar *resp
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerableint vulnerable
struct ddTabeleResults *tablepstruct ddTabeleResults *tablep
struct parResults *prespstruct parResults *presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablepstruct ddTableResults *tablep
int vulnerableint vulnerable
struct parResults *prespstruct parResults *presp
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin playstruct playTraceBin play
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBNstruct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plpstruct playTracesBin *plp
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBNstruct playTracesPBN *plpPBN
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
 
ErrorMessageint code Turns a return code into an error message string.
- + From ba22447aded774278c7bc4733af69cdd269484c0 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 05:12:25 +0100 Subject: [PATCH 183/199] Trying to get rid of zebra stripes through inline css --- doc/dll-description.md | 826 ++++++++++++++++++++--------------------- 1 file changed, 413 insertions(+), 413 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 2a30f35b..0f00a723 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -53,291 +53,291 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal
FunctionArgumentsFormatCommentFunctionArgumentsFormatComment
- + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - - + + - + - - + + - + - + - + - - + + - - + + - + - + - + - + - - + + - + - - + + - + - + - - + + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - - + + - + - + - - + + - + - + - - + + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - - + + - - + + - +
FunctionArgumentsFormatComment
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
int solutions
int mode
struct futureTricks *futp
int threadIndex
int threadIndex
 
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int solutions
int mode
struct futureTricks *futp
int threadIndex
 
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults *tablep
 
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults *tablep
 
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddtablesRes *resp
struct allParResultsa> *pres
struct allParResults *pres
 
 
CalcAllTablesPBNstruct  ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedp
 
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *presp
int vulnerable
 
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *presp
int dealer
int vulnerable
 
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster *presp
int dealer
int vulnerable
 
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.
char *resp
 
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *presp
int vulnerable
 
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
int vulnerable
 
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.
char *resp
 
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTabeleResults *tablep
struct parResults *presp
 
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablep
int vulnerable
struct parResults *presp
 
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
struct solvedPlay *solvedp
int thrId
 
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
struct solvedPlay *solvedp
int thrId
 
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plp
struct solvedPlays *solvedp
int chunkSize
 
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBN
struct solvedPlays *solvedp
int chunkSize
 
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
 
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
 
@@ -346,56 +346,56 @@ Common encodings are as follows - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -403,356 +403,356 @@ Common encodings are as follows
EncodingElementValue
SuitSpades0
Hearts1
Hearts1
Diamonds2
Clubs3
NT4
 
 
HandNorth0
East1
East1
South2
West3
 
 
SideN-S0
E-W1
E-W1
 
 
CardBit 2Rank of deuce
... 
... 
Bit 13Rank of king
Bit 14Rank of ace
 
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + @@ -762,27 +762,27 @@ Common encodings are as follows
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
StructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
StructFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
StructFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
StructFieldComment
parTextResultschar parText[2][128];
int equal;
StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
StructFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
StructFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
StructFieldComment
solvedPlayint number;
int tricks[53];Starting position and up to 52 cards
StructFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- + - + - + - + - + - + - + @@ -804,52 +804,52 @@ For equivalent cards, only the highest is returned, and lower equivalent cards a
SolveBoardSolveBoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
- + - + - + - + - + - + - + - + - + - + - + - + @@ -871,43 +871,43 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure
targetsolutionscomment
-11Find the maximum number of tricks for the side to play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with score set to 0.
02Return all cards that legal to play, with score set to 0.
1 .. 131If score is -1: Target cannot be reached.
If score is 0: In fact no tricks at all can be won.
If score is > 0: score will always equal target, even if more tricks can be won.
One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
- + - + - +
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablep
CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “ \*tablep” , which must be declared before calling CalcDDtable. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “\*tablep” , which must be declared before calling CalcDDtable. - + - + - + - + - + - + @@ -925,24 +925,24 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults \*prespstruct allParResults \*presp
- + - + - + - + - + - + @@ -950,18 +950,18 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
Number of strainsMaximum number of DD tables
532
440
353
280
1160
- + - + - + - + @@ -985,66 +985,66 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or
SolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp
int chunkSizeint chunkSize
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1094,21 +1094,21 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding.
ParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResults \*prespstruct parResultsDealer \*presp
int vulnerableint dealer
 int vulnerable
 
SidesPar 
struct ddTableResults \*tablep 
struct parResultsDealer \*sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResultsMaster \* prespstruct parResultsMaster \* presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
char \*respstruct parTextResults \*resp
- + - + - + - + - + @@ -1122,21 +1122,21 @@ Both functions are deprecated. Instead use one of the CalcDDtable functions foll
CalcParCalcParPBN
struct ddTableDeal dlstruct ddTableDealPBN dlN
int vulnerablestruct ddTableResults * tp
struct ddTableResults * tpint vulnerable
struct parResults *prespstruct parResults *presp
- + - + - + - + - + @@ -1154,21 +1154,21 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedp
int thrIdint thrId
- + - + - + - + - + @@ -1182,12 +1182,12 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedp
int chunkSizeint chunkSize
- + - + @@ -1214,87 +1214,87 @@ It is possible to ask DDS to give up its dynamically allocated memory by calling
SetMaxThreadsFreeMemory
int userThreadsvoid
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1302,84 +1302,84 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
- + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + - - + - - + +
Revision History
Rev A2006-02-25First issue
Rev A2006‑02‑25First issue
Rev B2006-03-20Updated issue
Rev B2006‑03‑20Updated issue
Rev C2006-03-28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev C2006‑03‑28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006-04-05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev D2006‑04‑05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006-05-29Updated issue. New error code –10 for number of cards > 52
Rev E2006‑05‑29Updated issue. New error code –10 for number of cards > 52
Rev F2006-08-09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F2006‑08‑09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006-08-14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F12006‑08‑14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006-08-26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev F22006‑08‑26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007-01-04New DDS release 1.1, otherwise no change compared to isse F2
Rev G2007‑01‑04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007-04-23DDS release 1.4, changes for parameter mode=2.
Rev H2007‑04‑23DDS release 1.4, changes for parameter mode=2.
Rev I2010-04-10DDS release 2.0, multi-thread support
Rev I2010‑04‑10DDS release 2.0, multi-thread support
Rev J2010-05-29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev J2010‑05‑29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010-10-27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev K2010‑10‑27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011-10-14Added SolveBoardPBN and CalcDDtablePBN
Rev L2011‑10‑14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012-07-06Added SolveAllBoards. -Rev N, 2012-07-16 Max number of threads is 8
Rev M2012‑07‑06Added SolveAllBoards. +Rev N, 2012‑07‑16 Max number of threads is 8
Rev O2012-10-21Max number of threads is configured at initial start-up, but never exceeds 16
Rev O2012‑10‑21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013-03-16Added functions CalcPar and CalcParPBN
Rev P2013‑03‑16Added functions CalcPar and CalcParPBN
Rev Q2014-01-09Added functions CalcAllTables/CalcAllTablesPBN
Rev Q2014‑01‑09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev R2014‑01‑13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014-01-13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014‑01‑13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014-03-01Added function SolveAllChunks
Rev T2014‑03‑01Added function SolveAllChunks
Rev U2014-09-15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +
Rev U2014‑09‑15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, AnalyseAllPlaysPBN
Rev V2014-10-14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +
Rev V2014‑10‑14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014-11-16Extended maximum number of tables when calling CalcAllTables.
Rev X2014‑11‑16Extended maximum number of tables when calling CalcAllTables.
From f35ee6d2703b935d9b4a132aa509a77be26336ac Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 05:16:31 +0100 Subject: [PATCH 184/199] UNDO: Trying to get rid of zebra stripes through inline css --- doc/dll-description.md | 772 ++++++++++++++++++++--------------------- 1 file changed, 386 insertions(+), 386 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 0f00a723..d5d236af 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -53,291 +53,291 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - - + + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - - + + - + - + - - + + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - - + + - + - + - - + + - + - + - - + + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - - + + - - + + - +
FunctionArgumentsFormatComment
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
int solutions
int mode
struct futureTricks *futp
int threadIndex
int threadIndex
 
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int solutions
int mode
struct futureTricks *futp
int threadIndex
 
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults *tablep
 
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults *tablep
 
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddtablesRes *resp
struct allParResults *pres
 
 
CalcAllTablesPBNstruct  ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedp
 
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *presp
int vulnerable
 
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer.
struct parResultsDealer *presp
int dealer
int vulnerable
 
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster *presp
int dealer
int vulnerable
 
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.
char *resp
 
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *presp
int vulnerable
 
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
int vulnerable
 
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.
char *resp
 
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTabeleResults *tablep
struct parResults *presp
 
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablep
int vulnerable
struct parResults *presp
 
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
struct solvedPlay *solvedp
int thrId
 
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
struct solvedPlay *solvedp
int thrId
 
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plp
struct solvedPlays *solvedp
int chunkSize
 
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBN
struct solvedPlays *solvedp
int chunkSize
 
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
 
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
 
@@ -346,56 +346,56 @@ Common encodings are as follows - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -403,356 +403,356 @@ Common encodings are as follows
EncodingElementValue
SuitSpades0
Hearts1
Hearts1
Diamonds2
Clubs3
NT4
 
 
HandNorth0
East1
East1
South2
West3
 
 
SideN-S0
E-W1
E-W1
 
 
CardBit 2Rank of deuce
... 
... 
Bit 13Rank of king
Bit 14Rank of ace
 
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + @@ -762,27 +762,27 @@ Common encodings are as follows
structFieldComment
dealint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
structFieldComment
dealPBNint trump;Suit encoding
int first;The hand leading to the trick. Hand encoding.
int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80];Remaining cards. PBN encoding.
structFieldComment
ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS
structFieldComment
ddTableDealsint noOfTables;Number of DD table deals in structure
struct ddTableDealPBN deals[MAXNOOFBOARDS/4];
structFieldComment
boardsint noOfBoards;Number of boards
struct deal[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
boardsPBNint noOfBoards;Number of boards
struct dealPBN[MAXNOOFBOARDS];
int target[MAXNOOFBOARDS];See SolveBoard
int solutions[MAXNOOFBOARDS];See SolveBoard
int mode[MAXNOOFBOARDS];See SolveBoard
structFieldComment
futureTricksint nodes;Number of nodes searched by the DD solver.
int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13];Suit of the each returned card. Suit encoding.
int rank[13];Rank of the returned card. Value range 2-14.
int equals[13];Lower-ranked equals. Holding encoding.
int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks.
structFieldComment
solvedBoardsint noOfBoards;
struct futureTricks solvedBoard [MAXNOOFBOARDS];
StructFieldComment
ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS
StructFieldComment
parResultschar parScore[2][16];First index is NS/EW. Side encoding.
char parContractsString[2][128];First index is NS/EW. Side encoding.
StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number;
int score;
char contracts[10][10];
StructFieldComment
parResultsMasterint score;
int number;
struct contractType contracts[10];
StructFieldComment
contractTypeint underTricks;
int overTricks;
int level;
int denom;
int seats;
StructFieldComment
parTextResultschar parText[2][128];
int equal;
StructFieldComment
playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand.
int suit[52];Suit encoding.
int rank[52];Encoding 2 .. 14 (not Card encoding).
StructFieldComment
playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand.
int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
StructFieldComment
playTracesBinint noOfBoards;
struct playTraceBin plays[MAXNOOFBOARDS / 10];
StructFieldComment
playTracesPBNint noOfBoards;
struct playTracePBN plays[MAXNOOFBOARDS / 10];
StructFieldComment
solvedPlayint number;
int tricks[53];Starting position and up to 52 cards
StructFieldComment
solvedPlaysint noOfBoards;
struct solvedPlay solved[MAXNOOFBOARDS];
- + - + - + - + - + - + - + @@ -804,52 +804,52 @@ For equivalent cards, only the highest is returned, and lower equivalent cards a
SolveBoardSolveBoardPBN
struct deal dl,struct dealPBN dl,
int target,int target,
int solutions,int solutions,
int mode,int mode,
struct futureTricks \*futp,struct futureTricks \*futp,
int threadIndexint threadIndex
- + - + - + - + - + - + - + - + - + - + - + - + @@ -871,15 +871,15 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure
targetsolutionscomment
-11Find the maximum number of tricks for the side to play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to play.Return all optimum cards and their scores.
01Return only one of the cards legal to play, with score set to 0.
02Return all cards that legal to play, with score set to 0.
1 .. 131If score is -1: Target cannot be reached.
If score is 0: In fact no tricks at all can be won.
If score is > 0: score will always equal target, even if more tricks can be won.
One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
- + - + - + @@ -890,24 +890,24 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablep
- + - + - + - + - + - + @@ -925,24 +925,24 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*resp
struct allParResults \*prespstruct allParResults \*presp
- + - + - + - + - + - + @@ -950,18 +950,18 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
Number of strainsMaximum number of DD tables
532
440
353
280
1160
- + - + - + - + @@ -985,66 +985,66 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or
SolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedp
int chunkSizeint chunkSize
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1094,21 +1094,21 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding.
ParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResults \*prespstruct parResultsDealer \*presp
int vulnerableint dealer
 int vulnerable
 
SidesPar 
struct ddTableResults \*tablep 
struct parResultsDealer \*sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablep
struct parResultsMaster \* prespstruct parResultsMaster \* presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*pres
char \*respstruct parTextResults \*resp
- + - + - + - + - + @@ -1122,21 +1122,21 @@ Both functions are deprecated. Instead use one of the CalcDDtable functions foll
CalcParCalcParPBN
struct ddTableDeal dlstruct ddTableDealPBN dlN
int vulnerablestruct ddTableResults * tp
struct ddTableResults * tpint vulnerable
struct parResults *prespstruct parResults *presp
- + - + - + - + - + @@ -1154,21 +1154,21 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedp
int thrIdint thrId
- + - + - + - + - + @@ -1182,12 +1182,12 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedp
int chunkSizeint chunkSize
- + - + @@ -1214,87 +1214,87 @@ It is possible to ask DDS to give up its dynamically allocated memory by calling
SetMaxThreadsFreeMemory
int userThreadsvoid
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1302,84 +1302,84 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
Revision History
Rev A2006‑02‑25First issue
Rev B2006‑03‑20Updated issue
Rev C2006‑03‑28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006‑04‑05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006‑05‑29Updated issue. New error code –10 for number of cards > 52
Rev F2006‑08‑09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006‑08‑14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006‑08‑26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007‑01‑04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007‑04‑23DDS release 1.4, changes for parameter mode=2.
Rev I2010‑04‑10DDS release 2.0, multi-thread support
Rev J2010‑05‑29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010‑10‑27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011‑10‑14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012‑07‑06Added SolveAllBoards. Rev N, 2012‑07‑16 Max number of threads is 8
Rev O2012‑10‑21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013‑03‑16Added functions CalcPar and CalcParPBN
Rev Q2014‑01‑09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014‑01‑13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014‑01‑13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014‑03‑01Added function SolveAllChunks
Rev U2014‑09‑15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, AnalyseAllPlaysPBN
Rev V2014‑10‑14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014‑11‑16Extended maximum number of tables when calling CalcAllTables.
From 86973dca4547bc1bad49bf8d13c77e86c4da4831 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 05:21:52 +0100 Subject: [PATCH 185/199] UNDO: nbsp; in tables --- doc/dll-description.md | 212 ++++++++++++++++++++--------------------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index d5d236af..e7cb78ed 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,282 +59,282 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play -int target +int target -int solutions +int solutions -int mode +int mode -struct futureTricks *futp +struct futureTricks *futp -int threadIndex +int threadIndex -  + -SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. +SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. -int target +int target -int solutions +int solutions -int mode +int mode -struct futureTricks *futp +struct futureTricks *futp -int threadIndex +int threadIndex -  + -CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) +CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) -struct ddTableResults *tablep +struct ddTableResults *tablep -  + -CalcDDtablePBN
struct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. +CalcDDtablePBN
struct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. -struct ddTableResults *tablep +struct ddTableResults *tablep -  + -CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded. +CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded. -int mode +int mode -int trumpFilter[5] +int trumpFilter[5] -struct ddtablesRes *resp +struct ddtablesRes *resp -struct allParResults *pres +struct allParResults *pres -  + -CalcAllTablesPBNstruct  ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format. +CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format. -int mode +int mode -int trumpFilter[5] +int trumpFilter[5] -struct ddTablesRes *resp +struct ddTablesRes *resp -struct allParResults *pres +struct allParResults *pres -  + -SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! +SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! -struct solvedBoards *solvedp +struct solvedBoards *solvedp -  + -SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. -struct solvedBoards *solvedp +struct solvedBoards *solvedp -int chunkSize +int chunkSize -  + -SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! -struct solvedBoards *solvedp +struct solvedBoards *solvedp int chunkSize -  + -SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded. -struct solvedBoards *solvedp +struct solvedBoards *solvedp int chunkSize -  + -Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. +Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. -struct parResults *presp +struct parResults *presp -int vulnerable +int vulnerable -  + -DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer. -struct parResultsDealer *presp +struct parResultsDealer *presp -int dealer +int dealer -int vulnerable +int vulnerable -  + -DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. +DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. -struct parResultsMaster *presp +struct parResultsMaster *presp -int dealer +int dealer -int vulnerable +int vulnerable -  + -ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. +ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. -char *resp +char *resp -  + -SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. +SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. -struct parResultsDealer *presp +struct parResultsDealer *presp -int vulnerable +int vulnerable -  + -SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. +SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. -struct parResultsMaster sidesRes[2] +struct parResultsMaster sidesRes[2] int vulnerable -  + -ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. +ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. -char *resp +char *resp -  + -CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! -int vulnerable +int vulnerable -struct ddTabeleResults *tablep +struct ddTabeleResults *tablep -struct parResults *presp +struct parResults *presp -  + -CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! -struct ddTableResults *tablep +struct ddTableResults *tablep -int vulnerable +int vulnerable -struct parResults *presp +struct parResults *presp -  + -AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. -struct playTraceBin play +struct playTraceBin play -struct solvedPlay *solvedp +struct solvedPlay *solvedp -int thrId +int thrId -  + -AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. -struct playTracePBN playPBN +struct playTracePBN playPBN -struct solvedPlay *solvedp +struct solvedPlay *solvedp -int thrId +int thrId -  + -AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. +AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. -struct playTracesBin *plp +struct playTracesBin *plp -struct solvedPlays *solvedp +struct solvedPlays *solvedp -int chunkSize +int chunkSize -  + -AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. +AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. -struct playTracesPBN *plpPBN +struct playTracesPBN *plpPBN -struct solvedPlays *solvedp +struct solvedPlays *solvedp -int chunkSize +int chunkSize -  + -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) -  + -FreeMemoryvoid Frees DDS allocated dynamical memory. +FreeMemoryvoid Frees DDS allocated dynamical memory. -  + From 9b663f9220b4fff6f878d9d17e623bbacbf8dac7 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 05:24:00 +0100 Subject: [PATCH 186/199] UNDO: Style in table --- doc/dll-description.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index e7cb78ed..69471027 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -54,7 +54,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -335,9 +335,6 @@ of the dealer. - - -
FunctionArgumentsFormatCommentFunctionArgumentsFormatComment
FreeMemoryvoid Frees DDS allocated dynamical memory.
From cd7cea9739c57a539da502e88b960cb698c13f24 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 05:26:55 +0100 Subject: [PATCH 187/199] REDO:   in tables --- doc/dll-description.md | 212 ++++++++++++++++++++--------------------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 69471027..4b9036e7 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -59,282 +59,282 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal -SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play +SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play -int target +int target -int solutions +int solutions -int mode +int mode -struct futureTricks *futp +struct futureTricks *futp -int threadIndex +int threadIndex - +  -SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. +SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format. -int target +int target -int solutions +int solutions -int mode +int mode -struct futureTricks *futp +struct futureTricks *futp -int threadIndex +int threadIndex - +  -CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) +CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.) -struct ddTableResults *tablep +struct ddTableResults *tablep - +  -CalcDDtablePBN
struct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. +CalcDDtablePBN
struct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format. -struct ddTableResults *tablep +struct ddTableResults *tablep - +  -CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded. +CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded. -int mode +int mode -int trumpFilter[5] +int trumpFilter[5] -struct ddtablesRes *resp +struct ddtablesRes *resp -struct allParResults *pres +struct allParResults *pres - +  -CalcAllTablesPBNstruct ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format. +CalcAllTablesPBNstruct  ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format. -int mode +int mode -int trumpFilter[5] +int trumpFilter[5] -struct ddTablesRes *resp +struct ddTablesRes *resp -struct allParResults *pres +struct allParResults *pres - +  -SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! +SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”! -struct solvedBoards *solvedp +struct solvedBoards *solvedp - +  -SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. +SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded. -struct solvedBoards *solvedp +struct solvedBoards *solvedp -int chunkSize +int chunkSize - +  -SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! +SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use! -struct solvedBoards *solvedp +struct solvedBoards *solvedp int chunkSize - +  -SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded. +SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded. -struct solvedBoards *solvedp +struct solvedBoards *solvedp int chunkSize - +  -Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. +Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table. -struct parResults *presp +struct parResults *presp -int vulnerable +int vulnerable - +  -DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge of the dealer. -struct parResultsDealer *presp +struct parResultsDealer *presp -int dealer +int dealer -int vulnerable +int vulnerable - +  -DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. +DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output. -struct parResultsMaster *presp +struct parResultsMaster *presp -int dealer +int dealer -int vulnerable +int vulnerable - +  -ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. +ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin. -char *resp +char *resp - +  -SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. +SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format. -struct parResultsDealer *presp +struct parResultsDealer *presp -int vulnerable +int vulnerable - +  -SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. +SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output. -struct parResultsMaster sidesRes[2] +struct parResultsMaster sidesRes[2] int vulnerable - +  -ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. +ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin. -char *resp +char *resp - +  -CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead! -int vulnerable +int vulnerable -struct ddTabeleResults *tablep +struct ddTabeleResults *tablep -struct parResults *presp +struct parResults *presp - +  -CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! +CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead! -struct ddTableResults *tablep +struct ddTableResults *tablep -int vulnerable +int vulnerable -struct parResults *presp +struct parResults *presp - +  -AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. +AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence. -struct playTraceBin play +struct playTraceBin play -struct solvedPlay *solvedp +struct solvedPlay *solvedp -int thrId +int thrId - +  -AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. +AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format. -struct playTracePBN playPBN +struct playTracePBN playPBN -struct solvedPlay *solvedp +struct solvedPlay *solvedp -int thrId +int thrId - +  -AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. +AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded. -struct playTracesBin *plp +struct playTracesBin *plp -struct solvedPlays *solvedp +struct solvedPlays *solvedp -int chunkSize +int chunkSize - +  -AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. +AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format. -struct playTracesPBN *plpPBN +struct playTracesPBN *plpPBN -struct solvedPlays *solvedp +struct solvedPlays *solvedp -int chunkSize +int chunkSize - +  -SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) +SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows) - +  -FreeMemoryvoid Frees DDS allocated dynamical memory. +FreeMemoryvoid Frees DDS allocated dynamical memory. - +  From a2ccbd58211b71323bf2a2976506b596ab84765c Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 06:18:09 +0100 Subject: [PATCH 188/199] tags in Data structure table --- doc/dll-description.md | 131 ++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 66 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 4b9036e7..9f6f1fc5 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -334,7 +334,6 @@ of the dealer. FreeMemoryvoid Frees DDS allocated dynamical memory. -  @@ -406,19 +405,19 @@ Common encodings are as follows -dealint trump;Suit encoding +dealint trumpSuit encoding -int first;The hand leading to the trick. Hand encoding. +int firstThe hand leading to the trick. Hand encoding. -int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. +int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. -int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. +int currentTrickRank[3]Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -unsigned int remainCards[4][4];1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. +unsigned int remainCards[4][4]1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. @@ -427,19 +426,19 @@ Common encodings are as follows structFieldComment -dealPBNint trump;Suit encoding +dealPBNint trumpSuit encoding -int first;The hand leading to the trick. Hand encoding. +int firstThe hand leading to the trick. Hand encoding. -int currentTrickSuit[3];Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played. +int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played. -int currentTrickRank[3];Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. +int currentTrickRank[3]Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -char remainCards[80];Remaining cards. PBN encoding. +char remainCards[80]Remaining cards. PBN encoding. @@ -449,7 +448,7 @@ Common encodings are as follows structFieldComment -ddTableDealunsigned int cards[4][4];Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding +ddTableDealunsigned int cards[4][4]Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding @@ -459,10 +458,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTables;Number of DD table deals in structure, at most MAXNOOFTABLES +ddTableDealsint noOfTablesNumber of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableDeal deals[X];X = MAXNOOFTABLES \* DDS_STRAINS +struct ddTableDeal deals[X]X = MAXNOOFTABLES * DDS_STRAINS @@ -472,10 +471,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTables;Number of DD table deals in structure +ddTableDealsint noOfTablesNumber of DD table deals in structure -struct ddTableDealPBN deals[MAXNOOFBOARDS/4]; +struct ddTableDealPBN deals[MAXNOOFBOARDS/4] @@ -485,19 +484,19 @@ Common encodings are as follows structFieldComment -boardsint noOfBoards;Number of boards +boardsint noOfBoardsNumber of boards -struct deal[MAXNOOFBOARDS]; +struct deal[MAXNOOFBOARDS] -int target[MAXNOOFBOARDS];See SolveBoard +int target[MAXNOOFBOARDS]See SolveBoard -int solutions[MAXNOOFBOARDS];See SolveBoard +int solutions[MAXNOOFBOARDS]See SolveBoard -int mode[MAXNOOFBOARDS];See SolveBoard +int mode[MAXNOOFBOARDS]See SolveBoard @@ -507,19 +506,19 @@ Common encodings are as follows structFieldComment -boardsPBNint noOfBoards;Number of boards +boardsPBNint noOfBoardsNumber of boards -struct dealPBN[MAXNOOFBOARDS]; +struct dealPBN[MAXNOOFBOARDS] -int target[MAXNOOFBOARDS];See SolveBoard +int target[MAXNOOFBOARDS]See SolveBoard -int solutions[MAXNOOFBOARDS];See SolveBoard +int solutions[MAXNOOFBOARDS]See SolveBoard -int mode[MAXNOOFBOARDS];See SolveBoard +int mode[MAXNOOFBOARDS]See SolveBoard @@ -528,22 +527,22 @@ Common encodings are as follows structFieldComment -futureTricksint nodes;Number of nodes searched by the DD solver. +futureTricksint nodesNumber of nodes searched by the DD solver. -int cards;Number of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7. +int cardsNumber of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7. -int suit[13];Suit of the each returned card. Suit encoding. +int suit[13]Suit of the each returned card. Suit encoding. -int rank[13];Rank of the returned card. Value range 2-14. +int rank[13]Rank of the returned card. Value range 2-14. -int equals[13];Lower-ranked equals. Holding encoding. +int equals[13]Lower-ranked equals. Holding encoding. -int score[13];-1: target not reached. Otherwise: Target of maximum number of tricks. +int score[13]-1: target not reached. Otherwise: Target of maximum number of tricks. @@ -553,10 +552,10 @@ Common encodings are as follows structFieldComment -solvedBoardsint noOfBoards; +solvedBoardsint noOfBoards -struct futureTricks solvedBoard [MAXNOOFBOARDS]; +struct futureTricks solvedBoard [MAXNOOFBOARDS] @@ -566,7 +565,7 @@ Common encodings are as follows StructFieldComment -ddTableResultsint resTable[5][4];Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. +ddTableResultsint resTable[5][4]Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. @@ -576,10 +575,10 @@ Common encodings are as follows structFieldComment -ddTablesResint noOfBoards;Number of DD table deals in structure, at most MAXNOOFTABLES +ddTablesResint noOfBoardsNumber of DD table deals in structure, at most MAXNOOFTABLES -struct ddTableResults results[X];X = MAXNOOFTABLES \* DDS_STRAINS +struct ddTableResults results[X]X = MAXNOOFTABLES \* DDS_STRAINS @@ -589,10 +588,10 @@ Common encodings are as follows StructFieldComment -parResultschar parScore[2][16];First index is NS/EW. Side encoding. +parResultschar parScore[2][16]First index is NS/EW. Side encoding. -char parContractsString[2][128];First index is NS/EW. Side encoding. +char parContractsString[2][128]First index is NS/EW. Side encoding. @@ -602,7 +601,7 @@ Common encodings are as follows StructFieldComment -allParResultsstruct parResults[MAXNOOFTABLES];There are up to 20 declarer/strain combinations per DD table +allParResultsstruct parResults[MAXNOOFTABLES]There are up to 20 declarer/strain combinations per DD table @@ -612,13 +611,13 @@ Common encodings are as follows StructFieldComment -parResultsDealerint number; +parResultsDealerint number -int score; +int score -char contracts[10][10]; +char contracts[10][10] @@ -628,13 +627,13 @@ Common encodings are as follows StructFieldComment -parResultsMasterint score; +parResultsMasterint score -int number; +int number -struct contractType contracts[10]; +struct contractType contracts[10] @@ -644,19 +643,19 @@ Common encodings are as follows StructFieldComment -contractTypeint underTricks; +contractTypeint underTricks -int overTricks; +int overTricks -int level; +int level -int denom; +int denom -int seats; +int seats @@ -666,10 +665,10 @@ Common encodings are as follows StructFieldComment -parTextResultschar parText[2][128]; +parTextResultschar parText[2][128] -int equal; +int equal @@ -679,13 +678,13 @@ Common encodings are as follows StructFieldComment -playTraceBinint number;Number of cards in the play trace, starting from the beginning of the hand. +playTraceBinint numberNumber of cards in the play trace, starting from the beginning of the hand. -int suit[52];Suit encoding. +int suit[52]Suit encoding. -int rank[52];Encoding 2 .. 14 (not Card encoding). +int rank[52]Encoding 2 .. 14 (not Card encoding). @@ -695,10 +694,10 @@ Common encodings are as follows StructFieldComment -playTracePBNint number;Number of cards in the play trace, starting from the beginning of the hand. +playTracePBNint numberNumber of cards in the play trace, starting from the beginning of the hand. -int cards[106];String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated. +int cards[106]String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated. @@ -708,10 +707,10 @@ Common encodings are as follows StructFieldComment -playTracesBinint noOfBoards; +playTracesBinint noOfBoards -struct playTraceBin plays[MAXNOOFBOARDS / 10]; +struct playTraceBin plays[MAXNOOFBOARDS / 10] @@ -721,10 +720,10 @@ Common encodings are as follows StructFieldComment -playTracesPBNint noOfBoards; +playTracesPBNint noOfBoards -struct playTracePBN plays[MAXNOOFBOARDS / 10]; +struct playTracePBN plays[MAXNOOFBOARDS / 10] @@ -734,10 +733,10 @@ Common encodings are as follows StructFieldComment -solvedPlayint number; +solvedPlayint number -int tricks[53];Starting position and up to 52 cards +int tricks[53];Starting position and up to 52 cards @@ -747,10 +746,10 @@ Common encodings are as follows StructFieldComment -solvedPlaysint noOfBoards; +solvedPlaysint noOfBoards -struct solvedPlay solved[MAXNOOFBOARDS]; +struct solvedPlay solved[MAXNOOFBOARDS] From 07f69f2d1954b38b7800c869b5b4102c7d8c3270 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 06:21:05 +0100 Subject: [PATCH 189/199] Last commit for the day --- doc/dll-description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 9f6f1fc5..fe54960c 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -643,7 +643,7 @@ Common encodings are as follows StructFieldComment -contractTypeint underTricks +contractTypeint underTricks int overTricks From cd0dbd5d1d6d5854c0874fcd70f736092427d7ce Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Mon, 22 Dec 2014 22:25:33 +0100 Subject: [PATCH 190/199] Added tags in functions --- doc/dll-description.md | 108 ++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index fe54960c..b253ec37 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -759,27 +759,27 @@ Common encodings are as follows - + - + - + - + - + - + - +
SolveBoardSolveBoardPBNSolveBoardSolveBoardPBN
struct deal dl,struct dealPBN dl,struct deal dlstruct dealPBN dl
int target,int target,int targetint target
int solutions,int solutions,int solutionsint solutions
int mode,int mode,int modeint mode
struct futureTricks \*futp,struct futureTricks \*futp,struct futureTricks *futpstruct futureTricks *futp
int threadIndexint threadIndexint threadIndexint threadIndex
@@ -868,15 +868,15 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure - + - + - +
CalcDDtableCalcDDtablePBNCalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBNstruct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults \* tablepstruct ddTableResults \* tablepstruct ddTableResults *tablepstruct ddTableResults *tablep
@@ -887,24 +887,24 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy - + - + - + - + - + - +
CalcAllTablesCalcAllTablesPBNCalcAllTablesCalcAllTablesPBN
struct ddTableDeals \*dealspstruct ddTableDealsPBN \*dealspstruct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp
int modeint modeint modeint mode
int trumpFilter[5]int trumpFilter[5]int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes \*respstruct ddTablesRes \*respstruct ddTablesRes *respstruct ddTablesRes *resp
struct allParResults \*prespstruct allParResults \*prespstruct allParResults *prespstruct allParResults *presp
@@ -947,18 +947,18 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + - +
SolveAllBoardsSolveAllChunksBinSolveAllChunksPBNSolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
struct boards \*bopstruct boards \*bopstruct boardsPBN \*bopstruct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards \* solvedpstruct solvedBoards \*solvedpstruct solvedBoards \*solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSizeint chunkSizeint chunkSize
@@ -982,66 +982,66 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
ParDealerParParDealerPar
struct ddTableResults \*tablepstruct ddTableResults \*tablepstruct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults \*prespstruct parResultsDealer \*prespstruct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealerint vulnerableint dealer
 int vulnerable int vulnerable
 
SidesPar SidesPar 
struct ddTableResults \*tablep struct ddTableResults *tablep 
struct parResultsDealer \*sidesRes[2] struct parResultsDealer *sidesRes[2] 
int vulnerable int vulnerable 
 
DealerParBinSidesParBinDealerParBinSidesParBin
struct ddTableResults \*tablepstruct ddTableResults \*tablepstruct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster \* prespstruct parResultsMaster \* prespstruct parResultsMaster *prespstruct parResultsMaster *presp
int vulnerableint dealerint vulnerableint dealer
 int vulnerable int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormatConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster \*presstruct parResultsMaster \*presstruct parResultsMaster *presstruct parResultsMaster *pres
char \*respstruct parTextResults \*respchar *respstruct parTextResults *resp
@@ -1091,21 +1091,21 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding. - + - + - + - + - +
CalcParCalcParPBNCalcParCalcParPBN
struct ddTableDeal dlstruct ddTableDealPBN dlNstruct ddTableDeal dlstruct ddTableDealPBN dlN
int vulnerablestruct ddTableResults * tpint vulnerablestruct ddTableResults *tp
struct ddTableResults * tpint vulnerablestruct ddTableResults *tpint vulnerable
struct parResults *prespstruct parResults *prespstruct parResults *prespstruct parResults *presp
@@ -1119,21 +1119,21 @@ Both functions are deprecated. Instead use one of the CalcDDtable functions foll - + - + - + - + - +
AnalysePlayBinAnalysePlayPBNAnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBNstruct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBNstruct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay \*solvedpstruct solvedPlay \*solvedpstruct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrIdint thrIdint thrId
@@ -1151,21 +1151,21 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one - + - + - + - + - +
AnalyseAllPlaysBinAnalyseAllPlaysPBNAnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards \*bopstruct boardsPBN \*bopPBNstruct boards *bopstruct boardsPBN *bopPBN
struct playTracesBin \*plpstruct playTracesPBN \*plpPBNstruct playTracesBin *plpstruct playTracesPBN *plpPBN
struct solvedPlays \*solvedpstruct solvedPlays \*solvedpstruct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSizeint chunkSizeint chunkSize
@@ -1179,12 +1179,12 @@ Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBi - + - +
SetMaxThreadsFreeMemorySetMaxThreadsFreeMemory
int userThreadsvoidint userThreadsvoid
From 70d849e9593c4f10fc882f62ec7b13fb1a91b70b Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 23 Dec 2014 02:09:44 +0100 Subject: [PATCH 191/199] Added last tags in functions --- doc/dll-description.md | 56 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index b253ec37..34abef42 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -764,7 +764,7 @@ Common encodings are as follows -struct deal dlstruct dealPBN dl +struct deal dlstruct dealPBN dl int targetint target @@ -776,7 +776,7 @@ Common encodings are as follows int modeint mode -struct futureTricks *futpstruct futureTricks *futp +struct futureTricks *futpstruct futureTricks *futp int threadIndexint threadIndex @@ -873,10 +873,10 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure -struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN +struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBNddTableDealPBN"> -struct ddTableResults *tablepstruct ddTableResults *tablep +struct ddTableResults *tablepstruct ddTableResults *tablep @@ -892,7 +892,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy -struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp +struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp int modeint mode @@ -901,10 +901,10 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy int trumpFilter[5]int trumpFilter[5] -struct ddTablesRes *respstruct ddTablesRes *resp - +struct ddTablesRes *respstruct ddTablesRes *resp +ddTablesRes"> -struct allParResults *prespstruct allParResults *presp +<struct allParResults *presp
struct allParResults *presp @@ -947,15 +947,15 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + - + - + @@ -987,10 +987,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + - + @@ -1005,10 +1005,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + - + @@ -1020,10 +1020,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + - + @@ -1038,10 +1038,10 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or - + - +
SolveAllBoardsSolveAllChunksBinSolveAllChunksPBNSolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boards *bopstruct boardsPBN *bopstruct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
struct ddTableResults *tablepstruct ddTableResults *tablepstruct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults *prespstruct parResultsDealer *prespstruct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealerSidesPar 
struct ddTableResults *tablep struct ddTableResults *tablep 
struct parResultsDealer *sidesRes[2] struct parResultsDealer *sidesRes[2] 
int vulnerable DealerParBinSidesParBin
struct ddTableResults *tablepstruct ddTableResults *tablepstruct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster *prespstruct parResultsMaster *prespstruct parResultsMaster *prespstruct parResultsMaster *presp
int vulnerableint dealerConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster *presstruct parResultsMaster *presstruct parResultsMaster *presstruct parResultsMaster *pres
char *respstruct parTextResults *respchar *respstruct parTextResults *resp
@@ -1096,16 +1096,16 @@ EW Par 120: W 1NT+1” when it matters who starts the bidding. -struct ddTableDeal dlstruct ddTableDealPBN dlN +struct ddTableDeal dlstruct ddTableDealPBN dlN -int vulnerablestruct ddTableResults *tp +int vulnerablestruct ddTableResults *tp -struct ddTableResults *tpint vulnerable +struct ddTableResults *tpint vulnerable -struct parResults *prespstruct parResults *presp +struct parResults *prespstruct parResults *presp @@ -1127,10 +1127,10 @@ Both functions are deprecated. Instead use one of the CalcDDtable functions foll struct deal dlstruct dealPBN dlPBN -struct playTraceBin playstruct playTracePBN playPBN +struct playTraceBin playstruct playTracePBN playPBN -struct solvedPlay *solvedpstruct solvedPlay *solvedp +struct solvedPlay *solvedpstruct solvedPlay *solvedp int thrIdint thrId @@ -1156,13 +1156,13 @@ The number of tricks are always seen from declarer’s viewpoint (he is the one -struct boards *bopstruct boardsPBN *bopPBN +struct boards *bopstruct boardsPBN *bopPBN -struct playTracesBin *plpstruct playTracesPBN *plpPBN +struct playTracesBin *plpstruct playTracesPBN *plpPBN -struct solvedPlays *solvedpstruct solvedPlays *solvedp +struct solvedPlays *solvedpstruct solvedPlays *solvedp int chunkSizeint chunkSize From 467cff324d8afb249431d83c090920e45d1ebea8 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 23 Dec 2014 02:31:16 +0100 Subject: [PATCH 192/199] Added all links --- doc/dll-description.md | 78 ++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 34abef42..4a4096ff 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -405,19 +405,19 @@ Common encodings are as follows -dealint trumpSuit encoding +dealint trumpSuit encoding -int firstThe hand leading to the trick. Hand encoding. +int firstThe hand leading to the trick. Hand encoding. -int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. +int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. int currentTrickRank[3]Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -unsigned int remainCards[4][4]1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. +unsigned int remainCards[4][4]1st index is Hand, 2nd index is Suit. remainCards is Holding encoding. @@ -426,19 +426,19 @@ Common encodings are as follows structFieldComment -dealPBNint trumpSuit encoding +dealPBNint trumpSuit encoding -int firstThe hand leading to the trick. Hand encoding. +int firstThe hand leading to the trick. Hand encoding. -int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played. +int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played. int currentTrickRank[3]Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played. -char remainCards[80]Remaining cards. PBN encoding. +char remainCards[80]Remaining cards. PBN encoding. @@ -448,7 +448,7 @@ Common encodings are as follows structFieldComment -ddTableDealunsigned int cards[4][4]Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. Holding +ddTableDealunsigned int cards[4][4]Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding. @@ -458,7 +458,17 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTablesNumber of DD table deals in structure, at most MAXNOOFTABLES +ddTableDealPBNchar cards[80]Encodes a deal. PBN encoding. + + + + + + +structFieldComment + + +ddTableDealsint noOfTablesNumber of DD table deals in structure, at most MAXNOOFTABLES struct ddTableDeal deals[X]X = MAXNOOFTABLES * DDS_STRAINS @@ -471,10 +481,10 @@ Common encodings are as follows structFieldComment -ddTableDealsint noOfTablesNumber of DD table deals in structure +ddTableDealsPBNint noOfTablesNumber of DD table deals in structure -struct ddTableDealPBN deals[MAXNOOFBOARDS/4] +struct ddTableDealPBN deals[X]X = MAXNOOFTABLES * DDS_STRAINS @@ -490,13 +500,13 @@ Common encodings are as follows struct deal[MAXNOOFBOARDS] -int target[MAXNOOFBOARDS]See SolveBoard +int target[MAXNOOFBOARDS]See SolveBoard -int solutions[MAXNOOFBOARDS]See SolveBoard +int solutions[MAXNOOFBOARDS]See SolveBoard -int mode[MAXNOOFBOARDS]See SolveBoard +int mode[MAXNOOFBOARDS]See SolveBoard @@ -512,13 +522,13 @@ Common encodings are as follows struct dealPBN[MAXNOOFBOARDS] -int target[MAXNOOFBOARDS]See SolveBoard +int target[MAXNOOFBOARDS]See SolveBoard -int solutions[MAXNOOFBOARDS]See SolveBoard +int solutions[MAXNOOFBOARDS]See SolveBoard -int mode[MAXNOOFBOARDS]See SolveBoard +int mode[MAXNOOFBOARDS]See SolveBoard @@ -533,13 +543,13 @@ Common encodings are as follows int cardsNumber of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7. -int suit[13]Suit of the each returned card. Suit encoding. +int suit[13]Suit of the each returned card. Suit encoding. int rank[13]Rank of the returned card. Value range 2-14. -int equals[13]Lower-ranked equals. Holding encoding. +int equals[13]Lower-ranked equals. Holding encoding. int score[13]-1: target not reached. Otherwise: Target of maximum number of tricks. @@ -565,7 +575,7 @@ Common encodings are as follows StructFieldComment -ddTableResultsint resTable[5][4]Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. +ddTableResultsint resTable[5][4]Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks. @@ -588,10 +598,10 @@ Common encodings are as follows StructFieldComment -parResultschar parScore[2][16]First index is NS/EW. Side encoding. +parResultschar parScore[2][16]First index is NS/EW. Side encoding. -char parContractsString[2][128]First index is NS/EW. Side encoding. +char parContractsString[2][128]First index is NS/EW. Side encoding. @@ -681,7 +691,7 @@ Common encodings are as follows playTraceBinint numberNumber of cards in the play trace, starting from the beginning of the hand. -int suit[52]Suit encoding. +int suit[52]Suit encoding. int rank[52]Encoding 2 .. 14 (not Card encoding). @@ -796,7 +806,7 @@ There is a “transposition table” memory associated with each th The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. -For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). +For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). @@ -913,9 +923,9 @@ 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. -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. +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. +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: @@ -973,7 +983,7 @@ It is important to understand the parallelism and the concept of a chunk. If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency. -The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. +The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk. No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. @@ -1046,15 +1056,15 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or
-The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions. +The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to [CalcDDtable](#CalcDDtable). Since the input is a table, there is no PBN and non-PBN version of these functions. Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. -The `vulnerable` parameter is given using Vulnerable encoding. +The `vulnerable` parameter is given using [Vulnerable](#Vulnerable) encoding. 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. -The DealerPar() function also uses knowledge of the `dealer` using Hand encoding. The rgument 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. +The DealerPar() function also uses knowledge of the `dealer` using [Hand](#Hand) encoding. The rgument 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. The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). @@ -1075,7 +1085,7 @@ DealerPar() and SidesPar() give each par contract as a separate text string: * “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. * SidesPar() give the par contract text strings as described above for each side. -DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the `parResultsMaster` structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. +DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the [`parResultsMaster`](#parResultsMaster) structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. Output example from ConvertToDealerTextFormat: @@ -1140,7 +1150,7 @@ Both functions are deprecated. Instead use one of the CalcDDtable functions foll AnalysePlayPBN is just like AnalysePlayBin, except for the input format. -The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number `thrId` and the transposition tables. +The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses [SolveBoard](#SolveBoard), the same comments apply concerning the thread number `thrId` and the transposition tables. As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: @@ -1174,7 +1184,7 @@ AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format. The AnalyseAllPlays\* 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. -Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin. +Concerning chunkSize, exactly the 21 same remarks apply as with [SolveAllChunksBin](#SolveAllChunksBin). From ed8ad572ee16319157b19231ce1ef19309ae7af0 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 23 Dec 2014 03:07:51 +0100 Subject: [PATCH 193/199] Corrections after review --- doc/dll-description.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 4a4096ff..49e08651 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -334,6 +334,13 @@ of the dealer. + + + + + +
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
ErrorMessageint codeTurns a return code into an error message string.
char line[80] +
@@ -821,7 +828,7 @@ play.
Return only one of the optimum cards and its score. -12Find the maximum number of tricks for the side to -play.Return all optimum cards and their scores. +play.
Return all optimum cards and their scores. 01Return only one of the cards legal to play, with @@ -883,7 +890,7 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure -struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBNddTableDealPBN"> +struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN struct ddTableResults *tablepstruct ddTableResults *tablep @@ -912,7 +919,7 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy struct ddTablesRes *respstruct ddTablesRes *resp -ddTablesRes"> + <struct allParResults *prespstruct allParResults *presp @@ -957,7 +964,7 @@ The maximum number of DD tables in a CallAllTables call depends on the number of - + @@ -1088,14 +1095,13 @@ DealerPar() and SidesPar() give each par contract as a separate text string: DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the [`parResultsMaster`](#parResultsMaster) structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. -Output example from ConvertToDealerTextFormat: +Output example from ConvertToDealerTextFormat: “Par 110: NS 2S NS 2H” -Output examples from ConvertToSidesTextFormat: - -“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT
+Output examples from ConvertToSidesTextFormat: +“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. +”NS Par -120: W 2NT EW Par 120: W 1NT+1” when it matters who starts the bidding.
SolveAllBoardsSolveAllChunksBinSolveAllChunksPBNSolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
From 9bec2fd6e625378ed7a94abdaccd7c7495b6dfb3 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 23 Dec 2014 10:14:17 +0100 Subject: [PATCH 194/199] Lots of closing-tag errors --- doc/dll-description.md | 124 ++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 71 deletions(-) diff --git a/doc/dll-description.md b/doc/dll-description.md index 49e08651..71e12028 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -2,7 +2,7 @@ Bo Haglund, Soren Hein, Bob Richardson Rev X, 2014-11-16 -Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ +Latest DLL issue with this description is available at [http://www.bahnhof.se/wb758135/](http://www.bahnhof.se/wb758135/) # Description of the DLL functions supported in Double Dummy Problem Solver 2.8 ## Callable functions @@ -18,7 +18,7 @@ The basic functions `SolveBoard` and `SolveBoardPBN` each solve a single hand a ### The Multi-Thread Double Dummy Solver Functions -The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand’s trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. +The double dummy trick values for all 5 \* 4 = 20 possible combinations of a hand's trump strain and declarer hand alternatives are solved by a single call to one of the functions `CalcDDtable` and `CalcDDtablePBN`. Threads are allocated per strain. in order to save computations. To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions `CalcAllTables` and `CalcAllTablesPBN`. @@ -34,8 +34,8 @@ The PAR calculation functions find the optimal contract(s) assuming open cards a Two alternatives are given: -1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. -2. The dealer hand is assumed to “start the bidding”. +1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT. +2. The dealer hand is assumed to “start the bidding”. The presentation of the par score and contracts are given in alternative formats. @@ -142,14 +142,14 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + - + @@ -159,7 +159,7 @@ The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `Anal - + @@ -259,7 +259,7 @@ of the dealer. - + @@ -302,7 +302,7 @@ of the dealer. - + @@ -341,6 +341,7 @@ of the dealer. +
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don’t use!SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don't use!
struct solvedBoards *solvedp struct ddTabeleResults *tablep
struct parResults *prespstruct parResults *presp
 
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plp
char line[80]
@@ -396,7 +397,7 @@ Common encodings are as follows Bit 14Rank of ace   -HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero. +HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.   PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K @@ -451,7 +452,6 @@ Common encodings are as follows - structFieldComment @@ -461,7 +461,6 @@ Common encodings are as follows - structFieldComment @@ -471,11 +470,10 @@ Common encodings are as follows - structFieldComment -ddTableDealsint noOfTablesNumber of DD table deals in structure, at most MAXNOOFTABLES +ddTableDealsint noOfTablesNumber of DD table deals in structure, at most MAXNOOFTABLES struct ddTableDeal deals[X]X = MAXNOOFTABLES * DDS_STRAINS @@ -484,11 +482,10 @@ Common encodings are as follows - structFieldComment -ddTableDealsPBNint noOfTablesNumber of DD table deals in structure +ddTableDealsPBNint noOfTablesNumber of DD table deals in structure struct ddTableDealPBN deals[X]X = MAXNOOFTABLES * DDS_STRAINS @@ -497,7 +494,6 @@ Common encodings are as follows - structFieldComment @@ -519,11 +515,10 @@ Common encodings are as follows - structFieldComment -boardsPBNint noOfBoardsNumber of boards +boardsPBNint noOfBoardsNumber of boards struct dealPBN[MAXNOOFBOARDS] @@ -544,10 +539,10 @@ Common encodings are as follows structFieldComment -futureTricksint nodesNumber of nodes searched by the DD solver. +futureTricksint nodesNumber of nodes searched by the DD solver. -int cardsNumber of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7. +int cardsNumber of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7. int suit[13]Suit of the each returned card. Suit encoding. @@ -565,11 +560,10 @@ Common encodings are as follows - structFieldComment -solvedBoardsint noOfBoards +solvedBoardsint noOfBoards struct futureTricks solvedBoard [MAXNOOFBOARDS] @@ -578,7 +572,6 @@ Common encodings are as follows - StructFieldComment @@ -588,7 +581,6 @@ Common encodings are as follows - structFieldComment @@ -601,20 +593,18 @@ Common encodings are as follows - StructFieldComment parResultschar parScore[2][16]First index is NS/EW. Side encoding. -char parContractsString[2][128]First index is NS/EW. Side encoding. +char parContractsString[2][128]First index is NS/EW. Side encoding. - StructFieldComment @@ -624,7 +614,6 @@ Common encodings are as follows - StructFieldComment @@ -640,7 +629,6 @@ Common encodings are as follows - StructFieldComment @@ -656,7 +644,6 @@ Common encodings are as follows - StructFieldComment @@ -678,7 +665,6 @@ Common encodings are as follows - StructFieldComment @@ -691,7 +677,6 @@ Common encodings are as follows - StructFieldComment @@ -707,7 +692,6 @@ Common encodings are as follows - StructFieldComment @@ -720,7 +704,6 @@ Common encodings are as follows - StructFieldComment @@ -733,7 +716,6 @@ Common encodings are as follows - StructFieldComment @@ -746,20 +728,18 @@ Common encodings are as follows - StructFieldComment solvedPlayint number -int tricks[53];Starting position and up to 52 cards +int tricks[53]Starting position and up to 52 cards - StructFieldComment @@ -801,19 +781,19 @@ Common encodings are as follows -SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don’t do that, and they also hide the implementation details such as transposition tables, see below. +SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don't do that, and they also hide the implementation details such as transposition tables, see below. -SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. +SolveBoard solves a single deal “dl” and returns the result in “\*futp” which must be declared before calling SolveBoard. If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard. -SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. +SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user. -There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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’t be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. +There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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't be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done. -The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. +The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions. -For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). +For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”). @@ -857,7 +837,7 @@ If the target cannot be achieved, only one card is returned with the score set a - + @@ -871,7 +851,7 @@ If the target cannot be achieved, only one card is returned with the score set a Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, and we may use it for something else in the future. If you think you need it, let us know! -“Reuse” means “reuse the transposition table from the previous run with the same thread number”. +“Reuse” means “reuse the transposition table from the previous run with the same thread number”. For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for `deal.first`. The Trump suit is the same. 1st call, East leads: `SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1` @@ -899,7 +879,7 @@ For mode = 2 it is the responsibility of the programmer using the DLL to ensure
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don't always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
CalcDDtablePBN is just like CalcDDtable, except for the input format. -CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “\*tablep” , which must be declared before calling CalcDDtable. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “\*tablep” , which must be declared before calling CalcDDtable. @@ -928,11 +908,11 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy 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. +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. -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. +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. +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: @@ -980,7 +960,7 @@ The maximum number of DD tables in a CallAllTables call depends on the number of
-`SolveAllChunks` is an alias for SolveAllChunksPBN; don’t use it. +`SolveAllChunks` is an alias for SolveAllChunksPBN; don't use it. `SolveAllBoards` used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows. @@ -1019,7 +999,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or   -SidesPar  +SidesPar  struct ddTableResults *tablep  @@ -1034,7 +1014,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or   -DealerParBinSidesParBin +DealerParBinSidesParBin struct ddTableResults *tablepstruct ddTableResults *tablep @@ -1065,7 +1045,7 @@ SolveAllBoards now detects repetitions automatically within a batch, whether or The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix `*tablep` which would often be the solution of a call to [CalcDDtable](#CalcDDtable). Since the input is a table, there is no PBN and non-PBN version of these functions. -Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. +Before the functions can be called, a structure of the type “parResults” , `parResultsDealer` or `parResultsMaster` must already have been defined. The `vulnerable` parameter is given using [Vulnerable](#Vulnerable) encoding. @@ -1075,21 +1055,21 @@ The DealerPar() function also uses knowledge of the `dealer` using [Hand](#Hand) The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar(). -In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. +In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460. There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives. Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples: -* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. -* “NS:NS 23S,N 23H”: Only North makes 3 hearts. -* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. +* “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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. +* “NS:NS 23S,N 23H”: Only North makes 3 hearts. +* “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding. DealerPar() and SidesPar() give each par contract as a separate text string: -* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. -* “3N-EW” means that E and W can both make exactly 3NT. -* “4N-W+1” 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’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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. +* “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick. +* “3N-EW” means that E and W can both make exactly 3NT. +* “4N-W+1” 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'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 “5N-W”. Par() would show “4N-W+1” as “W 45N”. * SidesPar() give the par contract text strings as described above for each side. DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the [`parResultsMaster`](#parResultsMaster) structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat. @@ -1097,12 +1077,12 @@ DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat. Output example from ConvertToDealerTextFormat: -“Par 110: NS 2S NS 2H” +“Par 110: NS 2S NS 2H” Output examples from ConvertToSidesTextFormat: -“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. -”NS Par -120: W 2NT -EW Par 120: W 1NT+1” when it matters who starts the bidding. +“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding. +”NS Par -120: W 2NT +EW Par 120: W 1NT+1” when it matters who starts the bidding. @@ -1158,11 +1138,11 @@ AnalysePlayPBN is just like AnalysePlayBin, except for the input format. The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses [SolveBoard](#SolveBoard), the same comments apply concerning the thread number `thrId` and the transposition tables. -As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer’s play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: +As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer's play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick: 9 10 10 10 10 9 9 -The number of tricks are always seen from declarer’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. +The number of tricks are always seen from declarer'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.
@@ -1195,7 +1175,7 @@ Concerning chunkSize, exactly the 21 same remarks apply as with [SolveAllChunksB
- + @@ -1285,6 +1265,7 @@ different number of boards in its first two arguments. + @@ -1326,7 +1307,7 @@ Invalid suit or rank supplied. (c) A played card is not held by the right player - + @@ -1393,5 +1374,6 @@ ConvertToDealerTextFormat, ConvertToSidesTextFormat + -
SetMaxThreadsFreeMemorySetMaxThreadsFreeMemory
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) Invalid suit or rank supplied. (c) A played card is not held by the right player.Rev B2006‑03‑20Updated issue
Rev C2006‑03‑28Updated issue. Addition of the SolveBoard parameter ”mode”Rev C2006‑03‑28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006‑04‑05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev X2014‑11‑16Extended maximum number of tables when calling CalcAllTables.
+ \ No newline at end of file From 6813762890829e0f1088e63d5500a25fb2a35b33 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 23 Dec 2014 10:35:51 +0100 Subject: [PATCH 195/199] Added html and pdf version of dll-description --- doc/dll-description.html | 1310 ++++++++++++++++++++++++++++++++++++++ doc/dll-description.pdf | Bin 0 -> 297944 bytes 2 files changed, 1310 insertions(+) create mode 100644 doc/dll-description.html create mode 100644 doc/dll-description.pdf diff --git a/doc/dll-description.html b/doc/dll-description.html new file mode 100644 index 00000000..7f642c9f --- /dev/null +++ b/doc/dll-description.html @@ -0,0 +1,1310 @@ + + + + + + +
+ + +

Bo Haglund, Soren Hein, Bob Richardson

+

Rev X, 2014-11-16

+

Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/

+

Description of the DLL functions supported in Double Dummy Problem Solver 2.8

+

Callable functions

+

The callable functions are all preceded with extern "C" __declspec(dllimport) int __stdcall. The prototypes are available in dll.h, in the include directory.

+

Return codes are given at the end.

+

Not all functions are present in all versions of the DLL. For historical reasons, the function names are not entirely consistent with respect to the input format. 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!

+

The Basic Functions

+

The basic functions SolveBoard and SolveBoardPBN each solve a single hand and are thread-safe, making it possible to use them for solving several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly.

+

The Multi-Thread Double Dummy Solver Functions

+

The double dummy trick values for all 5 * 4 = 20 possible combinations of a hand's trump strain and declarer hand alternatives are solved by a single call to one of the functions CalcDDtable and CalcDDtablePBN. Threads are allocated per strain. in order to save computations.

+

To obtain better utilization of available threads, the double dummy (DD) tables can be grouped using one of the functions CalcAllTables and CalcAllTablesPBN.

+

Solving hands can be done much more quickly using one of the multi-thread alternatives for calling SolveBoard. Then a number of hands are grouped for a single call to one of the functions SolveAllBoards, SolveAllChunksBin and SolveAllChunksPBN. The hands are then solved in parallel using the available threads.

+

The number of threads is automatically configured by DDS on Windows, taking into account the number of processor cores and available memory. The number of threads can be influenced using by calling SetMaxThreads. This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration.

+

Calling FreeMemory causes DDS to give up its dynamically allocated memory.

+

The PAR Calculation Functions

+

The PAR calculation functions find the optimal contract(s) assuming open cards and optimal bidding from both sides. In very rare cases it matters which side or hand that starts the bidding, i.e. which side or hand that is first to bid its optimal contract.

+

Two alternatives are given:

+
    +
  1. The PAR scores / contracts are calculated separately for each side. In almost all cases the results will be identical for both sides, but in rare cases the result is dependent on which side that “starts the bidding”, i.e. that first finds the bid that is most beneficial for the own side. One example is when both sides can make 1 NT.
  2. +
  3. The dealer hand is assumed to “start the bidding”.
  4. +
+

The presentation of the par score and contracts are given in alternative formats.

+

The functions Par, SidesPar and DealerPar do the par calculation; their call must be preceded by a function call calculating the double dummy table values.

+

The functions SidesParBin and DealerParBin provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, ConvertToSidesTextFormat and ConvertToDealerTextFormat, are included as examples.

+

It is possible as an option to perform par calculation in CalcAllTables and CalcAllTablesPBN.

+

The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration.

+

Double Dummy Value Analyser Functions

+

The functions AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin and AnalyseAllPlaysPBN take the played cards in a game or games and calculate and present their double dummy values.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionArgumentsFormatComment
SolveBoardstruct deal dlBinaryThe most basic function, solves a single hand from the beginning or from later play
int target
int solutions
int mode
struct futureTricks *futp
int threadIndex
 
SolveBoardPBNstruct dealPBN dlPBNPBNAs SolveBoard, but with PBN deal format.
int target
int solutions
int mode
struct futureTricks *futp
int threadIndex
 
CalcDDtablestruct ddTableDeal tableDealBinarySolves an initial hand for all possible declarers and denominations (up to 20 combinations.)
struct ddTableResults *tablep
 
CalcDDtablePBNstruct ddTableDealPBN tableDealPBNPBNAs CalcDDtable, but with PBN deal format.
struct ddTableResults *tablep
 
CalcAllTablesstruct ddTableDeals *dealspBinarySolves a number of hands in parallel. Multi-threaded.
int mode
int trumpFilter[5]
struct ddtablesRes *resp
struct allParResults *pres
 
CalcAllTablesPBNstruct  ddTableDealsPBN *dealspPBNAs CalcAllTables, but with PBN deal format.
int mode
int trumpFilter[5]
struct ddTablesRes *resp
struct allParResults *pres
 
SolveAllBoardsstruct boardsPBN *bopPBNConsider using this instead of the next 3 “Chunk” functions”!
struct solvedBoards *solvedp
 
SolveAllChunksBinstruct boards *bopBinarySolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksstruct boardsPBN *bopPBNAlias for SolveAllChunksPBN; don't use!
struct solvedBoards *solvedp
int chunkSize
 
SolveAllChunksPBNstruct boardsPBN" *bopPBNSolves a number of hands in parallel. Multi-threaded.
struct solvedBoards *solvedp
int chunkSize
 
Parstruct ddTableResults *tablepNo formatSolves for the par contracts given a DD result table.
struct parResults *presp
int vulnerable
 
DealerParstruct ddTableResults *tablepNo formatSimilar to Par(), but requires and uses knowledge +of the dealer.
struct parResultsDealer *presp
int dealer
int vulnerable
 
DealerParBinstruct ddTableResults *tablepBinarySimilar to DealerPar, but with binary output.
struct parResultsMaster *presp
int dealer
int vulnerable
 
ConvertToDealerTextFormatstruct parResultsMaster *presTextExample of text output from DealerParBin.
char *resp
 
SidesParstruct ddTableResults *tablepNo formatPar results are given for sides with the DealerPar output format.
struct parResultsDealer *presp
int vulnerable
 
SidesParBinstruct ddTableResults *tablepBinarySimilar to SidesPar, but with binary output.
struct parResultsMaster sidesRes[2]
int vulnerable
 
ConvertToSidesTextFormatstruct parResultsMaster *presTextExample of text output from SidesParBin.
char *resp
 
CalcParstruct ddTableDeal tableDealBinarySolves for both the DD result table and the par contracts. Is deprecated, use a CalcDDtable function plus Par() instead!
int vulnerable
struct ddTabeleResults *tablep
struct parResults *presp
 
CalcParPBNstruct ddTableDealPBN tableDealPBNPBNAs CalcPar, but with PBN input format. Is deprecated, use a CalcDDtable function plus Par() instead!
struct ddTableResults *tablep
int vulnerable
struct parResults *presp
 
AnalysePlayBinstruct deal dlBinaryReturns the par result after each card in a particular play sequence.
struct playTraceBin play
struct solvedPlay *solvedp
int thrId
 
AnalysePlayPBNstruct dealPBN dlPBNPBNAs AnalysePlayBin, but with PBN deal format.
struct playTracePBN playPBN
struct solvedPlay *solvedp
int thrId
 
AnalyseAllPlaysBinstruct boards *bopBinarySolves a number of hands with play sequences in parallel. Multi-threaded.
struct playTracesBin *plp
struct solvedPlays *solvedp
int chunkSize
 
AnalyseAllPlaysPBNstruct boardsPBN *bopPBNPBNAs AnalyseAllPlaysBin, but with PBN deal format.
struct playTracesPBN *plpPBN
struct solvedPlays *solvedp
int chunkSize
 
SetMaxThreadsint userThreadsPBNUsed at initial start and can also be called with a request for allocating memory for a specified number of threads. Is apparently¸mandatory on Linux and Mac (optional on Windows)
 
FreeMemoryvoid Frees DDS allocated dynamical memory.
 
ErrorMessageint codeTurns a return code into an error message string.
char line[80] +
+ +

Data structures

+

Common encodings are as follows

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EncodingElementValue
SuitSpades0
Hearts1
Diamonds2
Clubs3
NT4
 
HandNorth0
East1
South2
West3
 
SideN-S0
E-W1
 
CardBit 2Rank of deuce
... 
Bit 13Rank of king
Bit 14Rank of ace
 
HoldingA value of 16388 = 16384 + 4 is the encoding for the holding “A2” (ace and deuce).
The two lowest bits are always zero.
 
PBNExample:
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
structFieldComment
dealint trumpSuit encoding
int firstThe hand leading to the trick. Hand encoding.
int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding.
int currentTrickRank[3]Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
unsigned int remainCards[4][4]1st index is Hand, 2nd index is Suit. remainCards is Holding encoding.
structFieldComment
dealPBNint trumpSuit encoding
int firstThe hand leading to the trick. Hand encoding.
int currentTrickSuit[3]Up to 3 cards may already have been played to the trick. Suit encoding. Set to 0 if no card has been played.
int currentTrickRank[3]Up to 3 cards may already have been played to the trick. Value range 2-14. Set to 0 if no card has been played.
char remainCards[80]Remaining cards. PBN encoding.
structFieldComment
ddTableDealunsigned int cards[4][4]Encodes a deal. First index is hand. Hand encoding. Second index is suit. Suit encoding.
structFieldComment
ddTableDealPBNchar cards[80]Encodes a deal. PBN encoding.
structFieldComment
ddTableDealsint noOfTablesNumber of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableDeal deals[X]X = MAXNOOFTABLES * DDS_STRAINS
structFieldComment
ddTableDealsPBNint noOfTablesNumber of DD table deals in structure
struct ddTableDealPBN deals[X]X = MAXNOOFTABLES * DDS_STRAINS
structFieldComment
boardsint noOfBoardsNumber of boards
struct deal[MAXNOOFBOARDS]
int target[MAXNOOFBOARDS]See SolveBoard
int solutions[MAXNOOFBOARDS]See SolveBoard
int mode[MAXNOOFBOARDS]See SolveBoard
structFieldComment
boardsPBNint noOfBoardsNumber of boards
struct dealPBN[MAXNOOFBOARDS]
int target[MAXNOOFBOARDS]See SolveBoard
int solutions[MAXNOOFBOARDS]See SolveBoard
int mode[MAXNOOFBOARDS]See SolveBoard
structFieldComment
futureTricksint nodesNumber of nodes searched by the DD solver.
int cardsNumber of cards for which a result is returned. May be all the cards, but equivalent ranks are omitted, so for a holding of KQ76 only the cards K and 7 would be returned, and the “equals” field below would be 2048 (Q) for the king and 54 (6) for the 7.
int suit[13]Suit of the each returned card. Suit encoding.
int rank[13]Rank of the returned card. Value range 2-14.
int equals[13]Lower-ranked equals. Holding encoding.
int score[13]-1: target not reached. Otherwise: Target of maximum number of tricks.
structFieldComment
solvedBoardsint noOfBoards
struct futureTricks solvedBoard [MAXNOOFBOARDS]
StructFieldComment
ddTableResultsint resTable[5][4]Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. Suit encoding. Second index is declarer. Hand encoding. Each entry is a number of tricks.
structFieldComment
ddTablesResint noOfBoardsNumber of DD table deals in structure, at most MAXNOOFTABLES
struct ddTableResults results[X]X = MAXNOOFTABLES \* DDS_STRAINS
StructFieldComment
parResultschar parScore[2][16]First index is NS/EW. Side encoding.
char parContractsString[2][128]First index is NS/EW. Side encoding.
StructFieldComment
allParResultsstruct parResults[MAXNOOFTABLES]There are up to 20 declarer/strain combinations per DD table
StructFieldComment
parResultsDealerint number
int score
char contracts[10][10]
StructFieldComment
parResultsMasterint score
int number
struct contractType contracts[10]
StructFieldComment
contractTypeint underTricks
int overTricks
int level
int denom
int seats
StructFieldComment
parTextResultschar parText[2][128]
int equal
StructFieldComment
playTraceBinint numberNumber of cards in the play trace, starting from the beginning of the hand.
int suit[52]Suit encoding.
int rank[52]Encoding 2 .. 14 (not Card encoding).
StructFieldComment
playTracePBNint numberNumber of cards in the play trace, starting from the beginning of the hand.
int cards[106]String of cards with no space in between, also not between tricks. Each card consists of a suit (C/D/H/S) and then a rank (2 .. A). The string must be null-terminated.
StructFieldComment
playTracesBinint noOfBoards
struct playTraceBin plays[MAXNOOFBOARDS / 10]
StructFieldComment
playTracesPBNint noOfBoards
struct playTracePBN plays[MAXNOOFBOARDS / 10]
StructFieldComment
solvedPlayint number
int tricks[53]Starting position and up to 52 cards
StructFieldComment
solvedPlaysint noOfBoards
struct solvedPlay solved[MAXNOOFBOARDS]
+ +

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
SolveBoardSolveBoardPBN
struct deal dlstruct dealPBN dl
int targetint target
int solutionsint solutions
int modeint mode
struct futureTricks *futpstruct futureTricks *futp
int threadIndexint threadIndex
+ +

SolveBoardPBN is just like SolveBoard, except for the input format. Historically it was one of the first functions, and it exposes the thread index directly to the user. Later functions generally don't do that, and they also hide the implementation details such as transposition tables, see below.

+

SolveBoard solves a single deal “dl” and returns the result in “*futp” which must be declared before calling SolveBoard.

+

If you have multiple hands to solve, it is always better to group them together into a single function call than to use SolveBoard.

+

SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. Thus the user of DDS can create threads and call SolveBoard in parallel over them. The maximum number of threads is fixed in the DLL at compile time and is currently 16. So “threadIndex” must be between 0 and 15 inclusive; see also the function SetMaxThreads. Together with the PlayAnalyse functions, this is the only function that exposes the thread number to the user.

+

There is a “transposition table” memory associated with each thread. Each node in the table is effectively 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't be as efficient. The reuse of the transposition table can be controlled by the “mode” parameter, but normally this is not needed and should not be done.

+

The three parameters “target”, “solutions” and “mode” together control the function. Generally 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 controls the search behavior. See next page for definitions.

+

For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the futureTricks structure (see “equals”).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
targetsolutionscomment
-11Find the maximum number of tricks for the side to +play.
Return only one of the optimum cards and its score.
-12Find the maximum number of tricks for the side to +play.
Return all optimum cards and their scores.
01Return only one of the cards legal to play, with +score set to 0.
02Return all cards that legal to play, with score set to +0.
1 .. 131If score is -1: Target cannot be reached.
+If score is 0: In fact no tricks at all can be won.
+If score is > 0: score will always equal target, even if more tricks can be won.
+One of the cards achieving the target is returned.
1 .. 132Return all cards meeting (at least) the target.
+If the target cannot be achieved, only one card is returned with the score set as above.
any3Return all cards that can be legally played, with their scores in descending order.
 
modeReuse TT?comment
0Automatic if same trump suit and the same or nearly the same cards distribution, deal.first can be different.Do not search to find the core if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don't always search to find the score.
1Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play.
2Always
+ +

Note: mode no longer always has this effect internally in DDS. We think mode is no longer useful, +and we may use it for something else in the future. If you think you need it, let us know!

+

“Reuse” means “reuse the transposition table from the previous run with the same thread number”. +For mode = 2 it is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. The Trump suit is the same.

+

1st call, East leads: SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1

+

2nd call, South leads: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2

+

3rd call, West leads: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3

+

4th call, North leads: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0

+ + + + + + + + + + + + + + +
CalcDDtableCalcDDtablePBN
struct ddTableDeal tableDealstruct ddTableDealPBN tableDealPBN
struct ddTableResults *tablepstruct ddTableResults *tablep
+ +

CalcDDtablePBN is just like CalcDDtable, except for the input format. +CalcDDtable solves a single deal “ tableDeal ” and returns the double-dummy values for the initial 52 cards for all the 20 combinations of denomination and declarer in “*tablep” , which must be declared before calling CalcDDtable.

+ + + + + + + + + + + + + + + + + + + + + + + +
CalcAllTablesCalcAllTablesPBN
struct ddTableDeals *dealspstruct ddTableDealsPBN *dealsp
int modeint mode
int trumpFilter[5]int trumpFilter[5]
struct ddTablesRes *respstruct ddTablesRes *resp
<struct allParResults *prespstruct allParResults *presp
+ +

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.

+

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:

+ + + + + + + + + + + + + + + + + + + + + + + +
Number of strainsMaximum number of DD tables
532
440
353
280
1160
+ + + + + + + + + + + + + + + + + + +
SolveAllBoardsSolveAllChunksBinSolveAllChunksPBN
struct boards *bopstruct boards *bopstruct boardsPBN *bop
struct solvedBoards *solvedpstruct solvedBoards *solvedpstruct solvedBoards *solvedp
int chunkSizeint chunkSize
+ +

SolveAllChunks is an alias for SolveAllChunksPBN; don't use it.

+

SolveAllBoards used to be an alias for SolveAllChunksPBN with a chunkSize of 1; however this has been changed in v2.8, and we now recommend only to use SolveAllBoards and not the chunk functions any more; explanation follows.

+

The SolveAll* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 200 boards are permitted per call.

+

It is important to understand the parallelism and the concept of a chunk.

+

If the chunk size is 1, then each of the threads starts out with a single board. If there are four threads, then boards 0, 1, 2 and 3 are initially solved. If thread 2 is finished first, it gets the next available board, in this case board 4. Perhaps this is a particularly easy board, so thread 2 also finishes this board before any other thread completes. Thread 2 then also gets board 5, and so on. This continues until all boards have been solved. In the end, three of the threads will be waiting for the last thread to finish, which causes a bit of inefficiency.

+

The transposition table in a given thread (see SolveBoard) 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. If the chunk size is 2, then initially thread 0 gets boards 0 and 1, thread 1 gets boards 2 and 3, thread 2 gets boards 4 and 5, and thread 3 gets boards 6 and 7. When a thread is finished, it gets two new boards in one go, for instance boards 8 and 9. The transposition table in a given thread is reused within a chunk.

+

No matter what the chunk size is, the boards are solved in parallel. If the user knows that boards are grouped in chunks of 2 or 10, it is possible to force the DD solver to use this knowledge. However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch.

+

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!

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParDealerPar
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResults *prespstruct parResultsDealer *presp
int vulnerableint dealer
 int vulnerable
 
SidesPar 
struct ddTableResults *tablep 
struct parResultsDealer *sidesRes[2] 
int vulnerable 
 
DealerParBinSidesParBin
struct ddTableResults *tablepstruct ddTableResults *tablep
struct parResultsMaster *prespstruct parResultsMaster *presp
int vulnerableint dealer
 int vulnerable
 
ConvertToDealerTextForamatConvertToSidesTextFormat
struct parResultsMaster *presstruct parResultsMaster *pres
char *respstruct parTextResults *resp
+ +

The functions Par, DealerPar, SidesPar, DealerParBin and SidesParBin calculate the par score and par contracts of a given double-dummy solution matrix *tablep which would often be the solution of a call to CalcDDtable. Since the input is a table, there is no PBN and non-PBN version of these functions.

+

Before the functions can be called, a structure of the type “parResults” , parResultsDealer or parResultsMaster must already have been defined.

+

The vulnerable parameter is given using Vulnerable encoding.

+

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.

+

The DealerPar() function also uses knowledge of the dealer using Hand encoding. The rgument 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.

+

The SidesPar() function is similar to the Par() function, the only difference is that the par results are given in the same format as for DealerPar().

+

In Par() and SidesPar() there may be more than one par score; in DealerPar() that is not the case. Par() returns the scores as a text string, for instance “NS -460”, while DealerPar() and SidesPar() use an integer, -460.

+

There may be several par contracts, for instance 3NT just making and 5C just making. Each par contract is returned as a text string. The formats are a bit different betweeen the two output format alternatives.

+

Par() returns the par contracts separated by commas. Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in no trump are given as 345N. Examples:

+
    +
  • “NS:NS 23S,NS 23H”. North and South as declarer make 2 or 3 spades and hearts contracts, 2 spades and 2 hearts with an overtrick. This is from the NS view, shown by “NS:” meaning that NS made the first bid. 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.
  • +
  • “NS:NS 23S,N 23H”: Only North makes 3 hearts.
  • +
  • “EW:NS 23S,N 23H”: This time the result is the same when EW open the bidding.
  • +
+

DealerPar() and SidesPar() give each par contract as a separate text string:

+
    +
  • “4S*-EW-1” means that E and W can both sacrifice in four spades doubled, going down one trick.
  • +
  • “3N-EW” means that E and W can both make exactly 3NT.
  • +
  • “4N-W+1” 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'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 “5N-W”. Par() would show “4N-W+1” as “W 45N”.
  • +
  • SidesPar() give the par contract text strings as described above for each side.
  • +
+

DealerParBin and SidesParBin are similar to DealerPar and SidesPar, respectively, except that both functions give the output results in binary using the parResultsMaster structure. This simplifies the writing of a conversion program to get an own result output format. Examples of such programs are ConvertToDealerTextFormat and ConvertToSidesTextFormat.

+

After DealerParBin or SidesParBin is called, the results in parResultsMaster are used when calling ConvertToDealerTextFormat resp. ConvertToSidesTextFormat.

+

Output example from ConvertToDealerTextFormat:
+“Par 110: NS 2S NS 2H”

+

Output examples from ConvertToSidesTextFormat:
+“NS Par 130: NS 2D+2 NS 2C+2” when it does not matter who starts the bidding.
+”NS Par -120: W 2NT
+EW Par 120: W 1NT+1” when it matters who starts the bidding.

+ + + + + + + + + + + + + + + + + + + + +
CalcParCalcParPBN
struct ddTableDeal dlstruct ddTableDealPBN dlN
int vulnerablestruct ddTableResults *tp
struct ddTableResults *tpint vulnerable
struct parResults *prespstruct parResults *presp
+ +

CalcParPBN is just like CalcPar, except for the input format.

+

Each of these functions calculates both the double-dummy table solution and the par solution to a given deal.

+

Both functions are deprecated. Instead use one of the CalcDDtable functions followed by Par().

+ + + + + + + + + + + + + + + + + + + + +
AnalysePlayBinAnalysePlayPBN
struct deal dlstruct dealPBN dlPBN
struct playTraceBin playstruct playTracePBN playPBN
struct solvedPlay *solvedpstruct solvedPlay *solvedp
int thrIdint thrId
+ +

AnalysePlayPBN is just like AnalysePlayBin, except for the input format.

+

The function returns a list of double-dummy values after each specific played card in a hand. Since the function uses SolveBoard, the same comments apply concerning the thread number thrId and the transposition tables.

+

As an example, let us say the DD result in a given contract is 9 tricks for declarer. The play consists of the first trick, two cards from the second trick, and then declarer claims. The lead and declarer's play to the second trick (he wins the first trick) are sub-optimal. Then the trace would look like this, assuming each sub-optimal costs 1 trick:

+

9 10 10 10 10 9 9

+

The number of tricks are always seen from declarer'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.

+ + + + + + + + + + + + + + + + + + + + +
AnalyseAllPlaysBinAnalyseAllPlaysPBN
struct boards *bopstruct boardsPBN *bopPBN
struct playTracesBin *plpstruct playTracesPBN *plpPBN
struct solvedPlays *solvedpstruct solvedPlays *solvedp
int chunkSizeint chunkSize
+ +

AnalyseAllPlaysPBN is just like AnalyseAllPlaysBin, except for the input format.

+

The AnalyseAllPlays* 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.

+

Concerning chunkSize, exactly the 21 same remarks apply as with SolveAllChunksBin.

+ + + + + + + + + + + +
SetMaxThreadsFreeMemory
int userThreadsvoid
+ +

SetMaxThreads returns the actual number of threads.

+

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 threads 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.

+

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.

+

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 maximum 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 memory for this, DDS scales back the number of threads to fit within the memory.

+

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 memory, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitable number of threads on its own.

+

It may be possible, 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.

+

SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically.

+

It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. 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 the user program, so there is no need for the user to call this function before detaching. +

+

Return codes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueCodeComment
1RETURN_NO_FAULT 
-1RETURN_UNKNOWN_FAULTCurrently happens when fopen() returns an error or when AnalyseAllPlaysBin() gets a +different number of boards in its first two arguments.
-2RETURN_ZERO_CARDSSolveBoard(), self-explanatory.
-3RETURN_TARGET_TOO_HIGHSolveBoard(), target is higher than the number of tricks remaining.
-4RETURN_DUPLICATE_CARDSSolveBoard(), self-explanatory.
-5RETURN_TARGET_WRONG_LOSolveBoard(), target is less than -1.
-7RETURN_TARGET_WRONG_HISolveBoard(), target is higher than 13.
-8RETURN_SOLNS_WRONG_LOSolveBoard(), solutions is less than 1.
-10RETURN_SOLNS_WRONG_HISolveBoard(), solutions is higher than 3.
-11RETURN_TOO_MANY_CARDSSolveBoard(), self-explanatory.
-12RETURN_SUIT_OR_RANKSolveBoard(), either currentTrickSuit or currentTrickRank have wrong data.
-13RETURN_PLAYED_CARDSolveBoard(), card already played is also a card still remaining to play.
-14RETURN_CARD_COUNTSolveBoard(), wrong number of remaining cards for a hand.
-15RETURN_THREAD_INDEXSolveBoard(), thread number is less than 0 or higher than the maximum permitted.
-16RETURN_MODE_WRONG_LOSolveBoard(), mode is less than 0
-17RETURN_MODE_WRONG_HISolveBoard(), mode is greater than 2
-18RETURN_TRUMP_WRONGSolveBoard(), trump is not one or 0, 1, 2, 3, 4
-19RETURN_FIRST_WRONGSolveBoard(), first is not one or 0, 1, 2
-98RETURN_PLAY_FAULTAnalysePlay\*() family of functions. (a) Less than 0 or more than 52 cards supplied. (b) +Invalid suit or rank supplied. (c) A played card is not held by the right player.
-99RETURN_PBN_FAULTReturned from a number of places if a PBN string is faulty.
-101RETURN_TOO_MANY_THREADSCurrently never returned.
-102RETURN_THREAD_CREATEReturned from multi-threading functions.
-103RETURN_THREAD_WAITReturned from multi-threading functions when something went wrong while waiting for all threads to complete.
-201RETURN_NO_SUITCalcAllTables\*(), returned when the denomination filter vector has no entries.
-202RETURN_TOO_MANY_TABLESCalcAllTables\*(), returned when too many tables are requested.
-301RETURN_CHUNK_SIZESolveAllChunks\*(), returned when the chunk size is < 1.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Revision History
Rev A2006‑02‑25First issue
Rev B2006‑03‑20Updated issue
Rev C2006‑03‑28Updated issue. Addition of the SolveBoard parameter ”mode”
Rev D2006‑04‑05Updated issue. Usage of target=0 to list all cards that are legal to play
Rev E2006‑05‑29Updated issue. New error code –10 for number of cards > 52
Rev F2006‑08‑09Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters
Rev F12006‑08‑14Clarifications on conditions for returning scores for the different combinations of the values for target and solutions
Rev F22006‑08‑26New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank
Rev G2007‑01‑04New DDS release 1.1, otherwise no change compared to isse F2
Rev H2007‑04‑23DDS release 1.4, changes for parameter mode=2.
Rev I2010‑04‑10DDS release 2.0, multi-thread support
Rev J2010‑05‑29DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals
Rev K2010‑10‑27Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand
Rev L2011‑10‑14Added SolveBoardPBN and CalcDDtablePBN
Rev M2012‑07‑06Added SolveAllBoards. +Rev N, 2012‑07‑16 Max number of threads is 8
Rev O2012‑10‑21Max number of threads is configured at initial start-up, but never exceeds 16
Rev P2013‑03‑16Added functions CalcPar and CalcParPBN
Rev Q2014‑01‑09Added functions CalcAllTables/CalcAllTablesPBN
Rev R2014‑01‑13Updated functions CalcAllTables/CalcAllTablesPBN
Rev S2014‑01‑13Updated functions CalcAllTables/CalcAllTablesPBN
Rev T2014‑03‑01Added function SolveAllChunks
Rev U2014‑09‑15Added functions DealerPar, SidesPar, AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin, +AnalyseAllPlaysPBN
Rev V2014‑10‑14Added functions SetMaxThreads, FreeMemory, DealerParBin, SidesParBin, +ConvertToDealerTextFormat, ConvertToSidesTextFormat
Rev X2014‑11‑16Extended maximum number of tables when calling CalcAllTables.
+ +
+ + \ No newline at end of file diff --git a/doc/dll-description.pdf b/doc/dll-description.pdf new file mode 100644 index 0000000000000000000000000000000000000000..de32cc0c556aecd5bc7106b250d0dfc9cf9002b2 GIT binary patch literal 297944 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

nF=ECO^D?fdTxV`OoKg#|h+;XX}R zTdkRjhRl3)%#diPd#ZzIwoF++Kx@>Q!dLH~G-6b*QSZRbdrmZU%Bc4t`FzC# zy7~I~hK0sO?nRzD?}Mpz>5DRyiZqhyNq2bJ4}oP*rf&7p3aQ!2?5)C<4mO(;oMtIy z`9e{;u)W}vYO~aCm&xRGnWbTuOh#Q&8VIS?M6LFysoItmak+>GrA@(_xr1~j(hGR- z!en6k2{;LafFZ*FwgrQ8p}>RjnYNcAC=Eb34YA`LB9^}P(ok2&%-e872kVQO3 ze-;UAj2a0>5t$ezg?v-+ny zZ=5sk-dG7MSw?avZ?Conx(5~xj2%c$iebg0C-<8)^PXRacW1Mr?)6bmTvb{%AkrJ> z!!VRbHp-)r=%TjK?rGv#Vos|_3F~xDh0ozG^!uF-P9{b_vsvvbV{tU1ww8&9Q1prh zn>no4J8cD7Ou=bxxUkTfm72-0IL!!$Le5MC!&9OqHcCPYe;{Nl#1)zgKw+Z_sV}5< zkkgL1gF4E&5Xi^?*(%vV*>Tw!nMhU`3S~j2CX;41qDM3Zg8_7!va9vky3@Kd3~Chh znPy2!uDO-1bk8zRrm3!NM$?wGX03^(F8hbp3)gkORUay8Pb4jxkPV01D%#801{=|~ zZ3SuD*S>91(k5_Oq4z?YWCJzcgO#*CPlR^`52aK9zeGpXh=^LI3~Mw_nb+=thc|8_`*fVXf9_4MiYblTOpa!JsqZ^M|YjxMB$bSWzl6E0swLf|dKtdW{2<#p^9bjK&KPcc3k^O3|M?*j}TeDbmM#F2Yh3B@jdDQMwkolUV zJlJLf+YoOpxgd*6xepghq55xxK&mg@;Y^C4(|?!2^2F9>%-$vgwZg?c%^2T$S4Saq zzzZt*--`fc@GU}z?@xGz(IS+>Hn*Y&c{WoLwS5AAi9iY0OK77f3 z@^QgE3&@@C)?(_2yad3Ge4CBBI}G{eg(=ZuG%bb9v@pd*$YV#-awKU<3YjILA%&e8 z2epjIY^Z}Sz0T@ebK6B9N1Uuiohs?ap7ny}{6(MeakO6TKh53bmdnR9OW3`wVGr=m zJHkVK+x9TzDwoabj*YtHfe2Xed3NLT6w}mbm#>{CU9>0kDc%hS;Un^?;{)e8I7iMo z(y$V-l=p4S-A#$ z1ANq%9`gBuA*VaLP|%RP{Gz_wWJ#?7Nfyw z&q@=PED#vlR*@uMa7uq157Hr_1H+ROCvH!U5t=9i2KYbz|zT zR8eX)HN7A;sw-5dE=oO^dOY{%$x4~o5$ug%`b)}~ zJrXj_LK$ifTkPN}XPy*SJ0e{5ge@0MhUyMeqq_EgoI`)T43+T4+G?mJe)88nRDavr zhy3FCK#f3S$IVu3*RT*Nay$2qNgCS^STcgn(k#fw#9nsENqR?LxMB9 zsGQA81R?xAsKpU7Es6^ZB6CnH!L440TFKToH$E?t%ovar=Ipoyb& z$}(o1NRglvyt$?Hl2z|_+?y9{FlB$Cf(KmnsK82EqVc`zH?356(sa`DhvpC6S<_jo z_-)f?n$L8fm=0UM*L<&&*fchs(PXmlZ|nY4pVM2;Gg3(q$rPCvhifzN|#qMU$_~H+8W{GiX?utqJOarff@BD%q*trD@PL=o^gn zrd^gMt8|0#WkD`hliu%Sz2s{Swo1%ac}VrM}WwY3gIS(mGr{ zTywQfnr`W$F4A{0cD7ul?xU&HNflzb)GoG5)77c^R3olztb~{9)hZq&<{&TA2IX8z zkS%~ckOQkg1h*K166;+!hQ39o>t88QXjGhuC5E-_KFljFw~sS`t5G!kMUrxAAs~3*36U&K`a738f(_M3(M=aMIBqyF$`J_!VC{Yk@tb9OpSp;UB(!b{L=D& zhf3^KFZzqEbX0r#2k9BCqd&E<<8}5M}jqeb?O^`vC_( zmm@5!*rwIlvJ$UyzKGRp5DqplZZ}-3LXD()>nz72TpTu%v?%-YWCMJw zdLQJ4dHV32<-=z`7-hNX%hykf{r2q*n+LAFEw+!!V|_X* z&f9klUs>2~`LDv8Z1Zb{g9c0~9`pnvfbHlL4CoVjz>#Q1Y5tY={`uAUx0vRd=Go@k z7j}NKyS%rjXE|jmv9|oh?jM^^ntwA(?Cc@+mLm3AwkjM=FYRixs6_@Kol^30{9IN6 z+YQqytf7*U0&TEDv4GE7kXjJ*R&YE{e6O%6)+spJHO)m`ww{JyG&kfAMa!q9&q`mE zzA}Adx+vXR`E(O;U-Yi-L^HbT#P^wrowByAvR19|i9zC(UE(FJuyuxOcebe_d?i4R7O{Afcx-_60K^NEXXjLls%ChzKex7OiItsAv?-~1d_b&Bno zjeLB?l#*o<}oYy6SJ$)#efeZaYw$S%E+(m3F2G{n5Y;CW%nu>58 zW%cV2`r#5@YHcLbwrMn47j}Wks7K?-cGNfyIC!fL}<^#h(i+#Q(7H^Vo}wJ=_MyzK#pT*cVKz$t|(@ zLX0at_Lpe*+4$TQG(WmjS4g^ei~WTaQDuKq|E%)jfy&XQ>a2mqW0W_TZpa!_ydrCH z@e962U8A?Lpt0f|-8NMx(b3;D5hYwC4Qyc4UJ_jitVPIGcjYmXfyBy3F@6Y6j6ch=IZIcvp` z%>iq_6Bb?D`p3#_6RQ-;te9yptWHi8Ve&Lz9I(X?bA&EU)S6eOiJCJpK+vo4>0D)+ z6qN}BrJ?OjBm=+frI7H7Qx`w98LvSsbZ9ePCd7E9j-e5}Sjgk`ENF7ObpbfySaXB>KlV593!b)~2A3BNv04Dst(o zqe}{ku%HcPC++NC3h0w$QNlm}%EGy^HLb+HHBEdMQ2+EJtj={}03 zPO>r&9opL3{;uh@SocIa#U!R2`K}F&$EwM57wsiLtd$JozXL7wjE1y|lwSez6gbC! zMQxNSHjwg@@|Hz-a*u6zR z2;Ym~2;u`dUNiyJaOGB6n!;LuGWayA!h}p_mEAxlN%@pU^3E1m{oUt8Fi5Z@@)}^e^dNcRq+;4NGX^3`Sj@p9R-eAz@^`+^YdUJY_7mCse zm#>sXiWVh`?%91TqM1#QkiC0uJJl0tU?7Ik2i{QQ|%?$-ZF20 z?`ZEz??&$~?=i2`Yb!P{%JGU>{WS4P@h?8D+eE6cl>ad2l~&R zJ$92vrZLM?#w{PPvSB)#!f$rHzxOK>uDa#MsXNBq_SBQpZr`TXJWzREXSqeEm8)$T zPmgOoBp|3~wVM82ufB5P(9sNoXQJ$fqSiVfjRZES^h{O?O}0U!(Hnd!hl%C&)@-BI zYBKs9E(u2zo{+Ly(MZN^4S8iAFZzaY(G1Q3z)55Zr&o=fr(#=%e-J1=Mg#i{Ky8?2 zIA-7s*7Q*iT`UeJgcEJcn=u&^MCtzxNp5ODU9f#$ug3o$O&AL zHYDxZw6(r9fmg_O#ZK3@)IFko(nI`F=?T#fQmu*4C3&J!MFr`v=lxt4VDY(V~n1SDXxY`7eRO zeu;ZvkwpxDuVY`d|I8uKu!gC0YL4@<)#C$g!0; zaR?!wCNUu)X)4=t>|k4tEXNH{VwQa+6zCE{fI!)1AEhlx8fZQ=1lX`?fKX^dAAto* zOW=iecMEOW4YVb({m#t2k|jF<_Pu?wHTT@P=g#kZ=FH5Q(LcU(@4fGkul#r8ufI6) z$%&H_=U;q`Ix@G=$=p-l{q?WE3t!^R4AfZ+l39k%AMvv=@PGmKr?CnEUb4O$db{|n z@2vm#q5mjW6`osA5yhb{aX%eB@ULOsQwx)e&6 z(`0p(no7Bl>szLWP4_!?xgN7V2Drf@&TMq@Zn`$?^w>p97;QKEOI6xKa;4{g+WkST zA*x=p$A|CnJ?~?Dt_t2?M2Nhn2pfxhMfViRik#&qbLb4xMi+_KZ(edibajTmbJ7y= z)bg-s^b)@^=wiumBV+a|bIo2`?y7Gvfa)VK@|V3p)FGxTzRD-=d*;NOdploQVKtfU ziAPVpGI0@WU-=iA-b1A1pM5U7d*RrBJn-n5tCsV2bNRd*uM48-SyW8!s2fVB;P@-ASf*2es@k4uqI0ykh z??pN-uOdf0+kF~gjGP#Xv8y8FA2VUoQGC~-^0Kjvf6Hd6eaK+1nJ%P5zjzM*FAzDn z^5k4i_2MUOk`Np+s5v!JF;jB!G%B0?=%BzClYJsZlfOF@R2Mq4Ix1@n2dO@i{KD-S zR?cWm?r`~u@-yYET@3@RQzlbD6RAQqxaKG$e+r>M z6&N5#aV+M-z`2Db0Tfza>MuZu6P#6*4y8uT27ni1>?~A)1=nfHn!959ur+2Kvc6`O zTb=bIPvcjm<O zaCNnL-ki6JeP5wtXx$RJ6#b{GM~iK@zwx7s7k~7|?XTQ@_s@QI_ua2BryimjAPbFnb*yr?>!QHOu@!eK zN0j&A`8^Y^QqL$oqJPU+3U?yCYyO4O4@s zVqJAbMYuXpYGOrwugCgz8oi#?1Wcm+stv7^>{qgV`#>yMAEvvv1C5wC`N&I4N`Tyr zNUk!mYK`E0&w-(zcr>P+jr>B*@#@pnO!ZOx`$J6&<5{mpqGYH^Z2s$4xnmB9387I;0f65Te%BN_o zs;)E>h*vD%d41;{>%Iyj4Bx~b=@|32k#%#!{kg6PRD8ksxwv}af`3>x{+Fzf%C5h$ zQWzcoD7&$%B_pHH0nKd+Gm?Rwx-C`~aMn6w&K1rsXWIGqPL)M(x{e2HRjJclr%(iR zHji_c6|7a+3(Qe`-%}o?UdJN*4Bi0mGcedN$mI&bx{SxXv*0V+rpBYDaY~Ek)=xj4 zHY`QC-W=9oy=8`QBhZro#O8+Y?{8^yeIX1QrX??8l*I zJAs?)nfsnbrIXJevgun(iLVl`qu1CnPTRWC@_h?)GJ?zavQSlNS)`=CsjxLPr?fS) ziQg2|_E>PxGRwl0^UF%#4!s@uDD+X}V(4N-Jv%fzvZ-)W{XTwQP+3?X3?floX|uY@ zLzw$8@?oEkWU4c@`lv%LSeU+bL7y)W40wX5vW`kcb#;5By1FhBsEpK`wKO3^m^B!* zY`{!b@L{ANF5f$L)Ajp+o3~UHk@$tBrRzearA47YMW`@TSSZv-`1<-tkhgFa0R?%4 zg2+-|$SZ<45cPPhQMa-vT2U9RtgNVDv{BBC)KSc^JQ*r#l0h7NC{)-{e+=(IA&Air zMaCkG5UGxQEh38$sViu(KpzKMc1Sa(VN4o9Qw;#ow@Qt3)-(7KM7GX!=lGG*;~|Le z74^I)?!{zzRa$J%xYF61ZkJby^GKG-Gl#s*WC85VAy0#Nb=HbkdnLUdO1!q@VtN%tm5l>#+4UD|Dc`>xkV0mdXl{uit@c9U%LNHq&s8&=IShrti;bB z?22|q8EZB+7#j^u#@WVZ;~Znm*k)Xy;fi##bcfvsE9Av^7G^p;ovKbxT9x)FW~pjD z3seg{9V$h&x?v8Lz4vD0+3hW}XU}N~G+2!!$}4bqIrkcOmOIbM5oh9JoQ!KXaGcQ) zu!elJvqJ$>fC;pF0|B2m5SmpjM%J0?n7a0GU0roJFsnUAA`|bm;kNeHwzgPnpfarV z7FAW26nK~sPAw;THBcKREKXJ0>SA@!kscxhc#&)jwjE~}}mnA1k1KcJo!6qI##3@>PJ zUl6@!?f4OTM#=-RRSOd1uTywO+vk13g(e24I1M&|Kt@-Ya@8O95;DB4_BpOvw;JFQlS zGr&!^xx}u-Ko09@mwFS?<}#s>Da1@Oy!7?$qTy8=ZB*i8_$(4&#BC|?%T-{5ah#de zu!8G7Cw7vKz(mcjd#d+<`Q;?G*HmXOSzaRJjb8vI|E0X5zS!>K-5!NnrB zl<4nMZ=1gxSb5{-Th;3`;mwNA9H2%ja>ub$TZU1BZPt&-7K|5gN-V9uzMRt5u ztdXKJp zkEs8(vz1;Ac6yEJt@TeLY(mxOYhaokWp0l-IKMJRyt89~lT;p8o>rb!o>wZANAU-T z9H2rnwlj22ACIr!Of1^WnH6~(44y$Y80hem7Y>_v18+Yz`2lp<9~{zq&EBao&3e)e z648xmZNycICxMwvv004XRxJ;KnuS0`0yEj(R{++Siq~@R5CR)-wzu#ku<&G2=ji0g z7zY5$f+3|Q0V6Z|nsLT`C1+b4nLo_T5#-LaG*5hd;^f31Fn968 zEq5xfOPL!8OT7u!mxhf|t0xMKY6$zaY^fjbl&g?08d4VdjcTlR)m0#a;58PAD}(X^ zXKn5TFg3d})4v}#(?RUz#;~97(2zStQ=+RT?hKXGok1^PLiL)-U;nr`n58+TIGJ9w zN@E;4k$Xjn%A3z!ynp28|1~@@{@nX_iAz$+oN3)hUVm`+nKQc|I3w%aef_%h>C};l z$)8Lp#npAN3!>DZ>DzJowR?8FcACtH0qynz?Sd$buOWLcKRsw{DkaRZgy>{x((g!`exPcqVH5ZQ1y7x{)+EcnZFmr50~x}_La&++uo2n z6(Q9AD8NRh*bBoHj+V{{=dmN#`^thUm1?ogX|qF^*;b zeD=;W4?cK?e3_Sb6AE5@AwyC8*-tP&^3>$S;vJ_?@7VF$YvSo6^0l&2a{5S&zuAB* zG|Sjc+*a-m?tbMX7L`YwO7NYMMpka?G3EdaL}D?GG+-(Z5sYOeOAAX%LWO~Ht%0Y% zxvfy?u?6u46I&RHqH-nMYJv_A#z|zj)L; z@vTk^Yp?_(&W4AN<21Fe2Z(p*E7V6+)_LZ>j)cns1O1@ux_uK7N&(JnXP(X2+Na6M zd>~8n@tL4EW03;P@Xsqt0I%kzF?dDHf0%dh7B-f}MTZ}To$E=2x1 zkJDO|HbskOp3h>nSzFxm?hNdTJY&?ZwybUJYupsQvGJDZ9gTNHAL9@5?6;#we9TwW z<)y)*n%JD?h|6I#sI0ms6sfHa%ByA>4LTW%WM*e{&K$ql-^L!r^@n9b6|OppCY4MJ7*p_`x-8d?$#qh!xp(R;y} zE0|58{^Vj+V&hQ@w(!>v7tAWyPLMm?d-DbVBF9EI+?``mQkbR4y)Gz)wdSdqhK|XX z_X$|kG$S^5ne|WfsApUubwDj!dtn_y5m{Pf64JirQyZ!0Fh1s0MP^|+-|&;(Ju95L z>b)@Wkq-uUsG(FpX#;YV%jZRYVAefulNjqrxBpe`)hW{Xk{bgdR6@pHoG=U-4$ zo)&gKPAy(B!FA&^;oapI=cAggcJah?QLA5OIAct8cb-J|$}B_exL6!fML(0EZMQ(6 z7io6A&Ep8(hp~kza=hBojyc>T3>U-#E?8FFHpwkpiIlB>WVKW!$!VdezR)gGXF@bB z<8IZYqAXRKyA}cCBdV>#^SnOuqu9K0Sf7yI`pl5{S^VTlV#e9B0e*`E(FfcqI70!7E`k4X#v~kzBf8-izLpxVbat?&`28ws&G3bUi*;%$pI%4Qhas&LwG9` zKUzJbt$I|mT|=se+KTmHo3LxE@*m(PomMln83qNzgBP9NVE zeW{wdN8Mq>G>)kO)M-WzI(ah5@;Lrqf}=Xil+<2dSbVZ7Vf$XRL{4>#;&4^BAwaaG zWI2x4+D8|tJ0em(qmaiV5<@w<@%icU$RNP~i#xyT3a!UMRU@i~0L3nVM7cN+=o z_~b91Upx+}e=-!k^fu3)+IL#JoaCBNq3<+jO@sd7@~cTrrv)J8a;F;&Rz70O*^7UO!S6EGv@q<~hmYX75)fI7dq9`+@?*ZlM7Y0QtK2Z1?dT;5BC!xf*v8@< zdHs=xQQ?}fpuO-5Lf^Y%v9-cB?UYA}RpT|<}JY9ADfp`7`HEI32F6rl|*4!gyk_C`br-^ByY{9tq3+XH8uD*TX%i}xh zk#Z~G72QPwZqlQT%NHkgKZeK;TRqabzW63v%E%?Kkbzfv+1+Q-=g2u5nHMq-W!iYU zY6#nk{8i%Z9q4P|F~Za=mf3ZMRO{vuk)Pc^G|aYL)p)GIPnV!wxIPkFQe<#HLHD9@ zgop;sh1XdD7fTI)5_<@7{;=7UCx_J_Cwi$bjVMdq%|BLfg6?>4?Xpi8wtK#Su@5DE%5c;)Imvi}nRqh3icE3- z+rnRueVFHNGV8fu-EBCzByL@mdHTiI>b!hT+gqe-#97~FQ}Cg;XEQ}gPkmqHC&~HI z=#$JG9e0lF$F=N_#;lbEGT+&A-^>yD2;1wSIL4S1^J#;Vy_dXwJmh-jTe0oh-b;S@ z_FypS@P$P-gqx74g~xkCc^7*mLad2{vgq>hRz<&XU3|^MzYn*&vsk(oW0fi`}wfyr>Zv<$MEUyYOot+u`^0U^4{_UDa zlj-Z)rbZGtD8x9fh8XGOW-zH~Y8na*4r?0L-tN2|t@{=n8ixwhv+F$YTeXo^|3EpU$nqVvD5W2O27kaHcL!zNSB1td3J;^ZdRzx1H zk<8W7bGN0{duCy4Bq-i8jxTz$-83^9r>GdoO#1nm4P|mk4>t8<(Mjs zLHKg$%NAV-)e+j#szJE}819_b^bs<+GT4 z!kb~oD{6aeN|J%I)UJo5FEXjo|H#w(sS-Nx89DCPf4ZXxJnXI2(dLD*HyuLU5;0qTm{>>j4*1nV+PhWV;RVHHETC@JS*r`v9 zE34sCuM@xF7_eTVUoX7)qu?$_CBs{M=%+~r)%%?a7Y~25v#vE6x=frQeAd+uJH7eW zkE_HPq9XO_#2JET7ml7Vq{?P`5=g#amd>F1z$G`_X`$|&l+;}U<1?4f-1u$Ymia{6 zKeyP9xSsB*Ci`2cQtIkcZ19<+V#z3pm&8=_mM4_so~|gIP(JUseh=I1@!R<%?3`}n zx)%u|IrST?Z+Vq!3)SPOK9odhTM=+fybCmFNEWW~&%ju<>~*cK#Ik<~NVmkF={u zPX1)_cHsGO40j{6@*9@(kzcId>{womvN~6Ah9uff>8Q(;J}EVOCEqP=^B#_8YwgNo zO<%?N!kWt4j8#KiM~%WkX1RmMdEEAkLwIq9kb29>Ztu%1fyJNLVrxE^;4UcKIw27+ zxRk_r@lf8|o4DG<)%4|$bdR5GBbre;1dpk%*`QU#HIihCeLDMsHbCFzKE35BjjG?K zawNa6CrF&|ZSF3b73J4ZdBaB&hi|gdi7RGBSe`LP;ngUR_9?L-ceac0@Gj_#JanjhoJC1V$z zn|>ea4SkVV{Mp?TJlpAg(C_sb^&6h53XNA-)FVRg^$r+p&>Ho^NMF*4Ig7ES0%1oTMM~B9HK=6w>&THEypRS9yB{n&03&&tK9nw zW8CR*B*mPRhs;NPZp#o`Y#;Gvmjwxf@AvtLhmP8;<+@+aT{yeg8zY;z#9M15%SR}qW#NVJb zQvBMhy!X^Ez(#|Xav+SE=h&VeQeJ_LChu+u zVV8Q*u|%5KXQXr)cS4yd( zvBT5B`pJH_V0!OCZk!hW`jXekmG5c#$!lzrrBd zuzuRLGf9gwMl!4}%^`@Opc4Ajne!`7+_Ds>21zWE{EroC_%WNLJeCXCzT(L+iHR*LMQzFt=OQLyM{3+9)RLZ0>ZR1>wH|sjq3+nq^(gsCUl!KbB? z=p~FLlkNwn-YVwgVZmQ;x_)Br>-Z7{owvAdWu5-UaUUvja)Qd+2x;k#rzeHe?iH=A zRr;0(l#T1?i0E<$^#+eMG9XIWd4eY-U))RdY3WfXPSpw4x45pCDfjwC_JyaXWfosZ zsxTk}=W7(ZMlOYFdKH9bYrK{y?z@m7QB^{6 z0->sR;X;Dy29f7hp>J$-BuhOQ278FA&YqQdVK6A^TBl9Mz$?;6{!>zxQ^{jUfHw7{zR(ZR zC#f{|+s>)X3#d2Oeq(uAD`w;|WX<^jr5Zj!mfUg55 z(L(mlM32}YvDQgtrj7~L0 zornoUmjjX_W$YISTPy9EOGJ;KU?EYy8P`x*HhyP)R=|bp%H!ii_*P@Yk$PMZHIZmn zP~eiRos3-iq5>|C(Ixf`2yGp7_FSy=YL__{d3-YNS`YTG4Vl%1`njjMT1;--d0+I2 zKDb}JE#r8)T=rw&hsDtsWXWZUBkOJvj^{YDg*8p#my1+1&ud-OVu?ATL!ws(CrdH<4+Bq+9Cnw8AoF=LH=$4YG3>JKu@7NqsRP-#LO;5vgwPjdB%Bw`p1c;V zQuk8m%A%{3NLB~`_4IFI^jam3Q?_~d7wCnOL(en%s7l@;m@PVQ-BIR!`vddux){zg z$puc>y0@#EqC2cye+Cew4{>Kd)eHD}cBO?iNYr^sFY>*IOTo$$i!U2&BM*F4dnn6d z1E0%g=(#R1(+qZtayCs~7fV<3CjA&hrc+q$57)J7H1ZdHnz`P0pQvCeBK8^N3GQUO zVB5_(({|=WKk)$jiNLaD58ZG2>oGUH7uqxl!#c$HzfKWC99LHRoUn1Ti@osbV-8pI z8oJB%WLeN!F7-|L1b(>4Rc-PznxMYI6i0=7gV2ufP6LQ1)>Z#c%1Hk+>! za>#LSNT4c5+ZnFm*PWf|MjkSmR=d2cQ}beb%~5_g$WKy;1iP_Dg^hLnNzszT2`wJM zPp+;{eZR!qRc|6K|Khu3im2j$=9eAhvlL--c=W3o96M%YCah9L^HhuhYx#MUTc(sq zj9JZz=Z~^G6n=|YuBa8=^YD4Iyu^E^s)C6^i&>>@v{(|*=$d48cj745tnAV{XMLso zt-uefM)nGsxKnKvVt{5s(3jB`m2B;*c}`+(+9Cb;CFgmB#8R~%_*GOStNU5E0Ng3E zA3TBJ$GT!ke-Ol+0zalpzXT65cb1Yk<7Tc7IUFSlOK32=Av2Vm#$uTeW)Ba?=UMF$+PBMBQNY@ z)TX2)F>xm2ZX`h+*O}R(7aJcPXC-(Mb9$q1-l_4iX@XGuW72fw09QlW<*=`1Z zwDjU475?Sw{cQYPW%c6+_a6TYQJs%#b;o-9j5L+<9!iiOEtYbb>tzg*;GF*H*Z!1?}~zVw{H346ot^idA5j(Lg~=f zqkz8m5dG8A2KpvCLRPoXHz0D+A$X8<+;A8mAZTf6h5l>62W{QxxcSDO8ycldEX{B^ zg{;sQEN=ZW7x*;=13h~>btsIR0|D+V1eXu;a6k|+ZaNrv0WLP=rh`Dy7ZHN{69ISn z`bs*w<_5wBI_7q0L;YK{;4ls@Bnn0cECY_n*#*|_y>Z*!uDtu<%DGZHiH;p!r|Mrp-3nP z6bb>FL_j!rz>Sg^lKMcD`zHj0AvwTD^U%RyJX?fdaBgr-B{y1if_v1YXK!L<32cIn z^SXjKF8Uuj7DE$r171!}Fr&9H;54+dwl?6jcF;99(bF=vw=f4fx8u~e(&I$`r9djI zXd~RO>Y)&>Z542VKNAXp&_SV44mb>o!UzVf{B2$QZE_ez0E^~8ppZa5=zBNOf`T9s z9B?S?FHL(ty5BKwC=bsjKfBfqgMeE>QQX`Z4i&A;9Swx6bZqtaLlDCw63&5waiM_Y z!oY>1P!t^sxydtz-nR4Ffhe|riNbj}c!2omU=YMs;6Oq+fPm3~Xe(6cn45#(31~T( z+aCZuC=|f~~)A;bJ;(45D@Os+S=m}2yl-r1o0<8rH=A+)U?qz22XJjK2MYMxE{{+yaKkPXfuXl;FuN>*?_33U7=w&& zM~B$Sx!c$6BEkRvaI5hD5kS~M1;9cuHv<3jumG`>God`F&74VxfN}jXVC$kIncaRu z*^V>7fT?U|Y91s94DEx!Q2vmo(fGr_7KE4mdjb;B08yET4hql*Hw>Tx6i7*sJyx=R zzAz?<0E}@%Q1D%12*4T=3EQ>F1EhuoNDhS#(JJ31p)ziod*d8uyq?p0L^j0;n3YUrf8yX zUDOG!3`n`48E(r9cud~1&6~q5O9zOkRT7C%@U3P z&Hxf1CVK71{2@H>El`Z&Mxc#-uZ@5_4*UU-IVjw?r)JnMe#CeZM)4Tq{*&Sl-nvo1 zmQh^j47P)?5a4=vpd^e=4gzBB7~3|WqJsbxZ6;0>pbA0k+8Rhzjs~{&N>-ajhb})w zt!yoH?EkjyVWbPHG7cCzPGO`A17RPsH%{$JcPkk0pC}Sk007VJfn30|HbD_aymn~B ztiK7F|32ixaEU+y%*6%jXAB}ipx_+b2*fT#KUjh&5SzF+G3*X#Mga^9tZG-M2ZNe- zObCVK<^T+W@CfK^B{xuX^Xv_ef2gtdle{rvg#xGGLPsu)@j!u~(R^d{xNAHIm3UxK zB-&I!^|Mpp!2rvDz|RMqdXONS!chRvq5}^P4;P#c;OR}T!LYfB*g*qhp9YHw)<`6B z6D;f+>>iQ_6s`AK{DGAE2oNmM355;Ig{f8|G3d+F^MYk4qU>1ZM&H>t4yIEn^+z%>NVuZRIy8cC| zd-b?~CgBJk4j2fGyY2-{p92ceB*xee*uBs>7F~ZsKp6}HfNrzV@Q3;vQv~b>*?j=otsX=S~-D*IZ#x*dOYhU2DYzXP{(E zU5sg4Z`Z}>BJ}^ibuk8}WBOo!!s*uLI?hVAI$&yWFbYJ0)+rYcfJr+b0>%wRJLhie zbeH0O68a8^fPe~whZ{5&Av>+9osfs|eNkHj18D;bD_iINhnnq91Hhg;1BmTT!>%J@ z_}dSA7|-91Z74cSuJ}`IJE&ZN06_+1zFpRkAjY6U1V)k=)(*y25TITKK^hR;u2^75 z)E_IBtvn$IY;^ysLxTPq=;5OQ^)@*q1dJoLdfo?wPxL|S=Rj}?41iKF7XoGtTG^ZZ zau~o0f0)e(TI!fP+Zg}^hnCO2kjaiSK@p$}itf^5hF$Up7_*^k08Hl&1qa9#zGtep8}avV0|SBN|cd_0ciU;DtC@?St z!58=x6t&q5MFG1-g1ITiUJeMBVB+C6w&dP5n12QA2N^R^U`__gv^_C{8>kiCxBpiL z(RgqF_PO2K00YOJe(!c`W4AipiuU`lmt9$IHGI+3cG~7!4c}dA2PsS>XzQWS!y^oc zMR9?W5x%GN-nJIBF!#gZjt_2^q_ACZfJA}mI>09w^`ScqayqsLK@ASdI#3MkhHN;f z>Ohd$jV=EYvJb=s;UI#7Ce5C{9~?wbutBifWZqTc0Yq#hdWMf4&S8uO34#Cwg4kvA z03!B|22r4X1>pn+wn)%}Ty8oPcmdWh{-i+QdqAg{I$&!K1tw41bpQmtjq=}62<+LQ z*&N|YBAoHLb&%1P>z(V0j$Zo}PFoa+bu*CvCc9#$g%##3G+5?XEBRQ~Lw+X+Y zKul^&4Ag?4 zPY(mb*sZz(%%y<1P;}_!mc3=gzJf0pM4;EQc2~pT00x0x2?+XoK;*t81_Qe)oATLR zOhC_NVO(JSY-=%LHyrJY7ueR83LV-M(5QQJtcLDm(ZK*RM{l$oj0wPYGyyU)pamij z7*K8!gn*2U4i6YQ`?3HGirFeG(3v0DIG{-Pr@BJS%3R;X(r6!6y)8Si#DRvSdt?WN zf>zmHOuB6hd-Da@@!DQu+({VdrON+?gz=}1ip`9%^Vj}k2?GXZ*PG4?2Llu2X2Jl) z`DT|D4tBYKIQJwB%&OQv)CZzCFmTW}0?`i`JRCF!K(qy69aK$V^=KDe9E?RmK<&S| zlDN~yfdJrI^ zCq*3qxt-t#1+Bf!eF`{`9jI*4Ybx-)`xN_iY7Ap=bQ5v2&fH-Pj@}X2>(q+-XADgR z09k}fB6LCTj(t%bU}pS3J&;$BKJU-{d0v8A_62v9wY=nza4Vu z{s6js|7&CXLwrPUpl>dD@5IMFX9l(wy8l}?&iV1bDa zg?8~>k%A4Mza17~7%J#x12ibyr2-mP02J<)>gYX-zfA~}sbQesxP?A<0^>H2-$Q5% z<^I7u{&gP_@?X1&JMu z9RbsX-~>Lg?H&MI{$ucRN5tEE?3xe!ceX<7{?x)!V-H|1FF9^0&VVCfo5ds)I0I!SK$95gk!+WA7c1Fe<*WD#9;Xf)JPy}>_l+TwgfZQT?BkUBS3T%+dLSF0wXxE zO$i5wRC%^GR#9L%7d@uKz<~V^$zWie1gxTh=H)hf=+WFJ=J{9W^0~<9?F4o zlnz9IKa6vB$19i>sC}kH0I<+A@ZBXyba+6E7$eYKntwlh0}uuFfKZ^dv(r)9DKY+u zj?#{KZZG`qvCr*=-vc+$9f}zH#B5Rg8~gm*qTHdheLM)=hTaCK|9U)VYxF0ydHCsX zlY{PP4nq%vW&RO*7+1jP4&!|PlkjL^%{CW z{*QY+I4lA7V?lbu1Z@atT7aG8-75c}qc+BN;6SkGLuG$D%671}it$2pYh&}6!9V4N z5CEaj0UFdz+xmk52!&oX`-||2F_}N$jDPK}f%)uzNvZgki^$p z*X-sEbp42ajKfym*ki2+vTOv_e>QV39Gocvr*c5^WT(=Hg9R?|;Fn$ShS^EpPu;!a zjTm|uK=tqG?QeT)yQR73%r#im1e15V?K9WAlm1<|_}c&u-PGSIoj{W30b9jz;DhL8 zVmeTL|KY&h<`fOA6mOk&+82vE9R>){7&yqdrvU~5{TpzQ@h^0^ul~YrpLpx6CRm9B z&+gf@qphtk4TQ=(GV^IlEwS(`+`YjK56|it+g!?l9@$#Cs9W)GUfowI+KcEZ0gP@uj)6czt^77qG9 z9ESV9XkPw5wJ9-My->`e?Dj|v_CKuk{@<~L9y5cdn`{Hg|1?L#a0lCZjvx5hZSMZE z*=&d2a&`bu{o}^vlr+%?kJJO}bbt)qW(`TV^?DO0ftFjee$Q9bY?xO>nfM?1+1H}bW>LPr9GT6(TCTOexH2=e z@zY}CE3L=sxRZzY(E6gs(64&&)&lvF^_pMo8)-O+U0O39t{amv9?Re-*4GQB`Zzt- z%6o`h?KaAd=dCJ!uO)kkrv`egEq?UiZ*G+_-ncAecGOtV_#-p?`VntC^{d7YqWWS8 zls;*AL?9I zP`d>#@Sfl|VsbyRtG_y|GgD^lNrQ z3un@$X4*@5zb33-BeYGJbJxt<%dpz5jg#=s5|KJ)b)>HzVOLHiKCO|dFkC6qcthr8 z+poh$D7-9z&;_+387%d7IeVE@m!y;h@e?GmeCqAOV-rCv1A21B%ws_?9MY5pOJ{=W zyt_a1uO#XFI)Ctrx`{jN%o;M9Xxpw9e=o1GJ#Jp2Y1*sR!oMrtFymJfdH?tbiL#U5 zvV^^z5{{pmbhvm1Q(az!ja>=#utm6+U#H9CN($@?gfd@HIr|+wGJ+JyH@kQxSargM zy7+cv1w4W9-Cc@AnzbUyb4+B$SDmyjnvx{M4!E|6wJYkL8#jSUPf>+O;1`l6nGM`? zdZkS*>5`x^Sv{a$**w5k+01uqHr@zN+HB?1CE6#i4HO>rOV6Xy8C#^}74$AqBoJ0( zdq-BpE|=usNsqozh+zxpEzpL)geVo3CMr5{RytqdZo>K5ucQnOn&wyKs&VDO)ohQ! z<9%c(Y26-5d+zhFtj}?IoZkXx{0^DEPd@$oZn37op_CqH+;}bc^UKJB1 z-9$u^Zz8*)aLKH%3f@yys?&%B!mQakQiMHWR>aMAqYh!RBEvNHj<5=LfuFia<&Uu` z*VEYZIGBQce>z4cEb|qw>bhtig%l)`)b({41P~*cU|zlxpSWV$lRLd5OeG(NP?KI^)WS=h49MzAP=RXMQiEsKiW1bhaEp5%T3s=g=xFiuaMX^I zy7}AOf1TX!?d)_~q|}*b`qUR+G;7m)AH!pXtBNJQ6{02}*R3o`>`U>=v~1>EO7o;3 z@ETc!aLVu^Voax6IO4E zvTQ5u0(viUcSXF5=bMpCKAHI(d(kmbUbntJLcE}sc!6*ctK>qu3`9lU7n1!{H!F!; zZ_ty==|>xuol3ub+&%Hcu#d6!W&>nwSI_#58%KLZms#6gc$G)lh0FHDKvK}chEd4U zfBJ5(?l^}?7+FXiD*H)%CvIYi1Jg`vY5-XRds3ddKW|v6`H*pyQNpCPy=+_xRhO=$ z&^&wjG_j#D+3=L|vr7CzYUe)O!)0C#C(MS^Cw1$TXn2X#sU6Zr^H36$_vtRou+=K5 z6URHvI#4X6c5oA^*T>IU6RSr>2Q+?lr(N{4@OhjHohrU?sf3K$R4q|lFui@CfXSbo zV0dc!1+T+p0=vM8y4MmtP?(5CD`oM=*VYRhAER?_b|Aw}E%>L6S?0u4WLNt!Oc(0HmPreq>fG0D+?UAbvBwn#I^hZxDM_@F$cWJpChu4KqbA?}dhD>;=_ z2GKB5(_;#(O^FIV;t4)J_H|0*?amM742a``j8$afp4OUE-1+%M^ju_XGkuG^TI{7} z{%~T3BkeL(nIxt+VlBVnMGOo}8~WKDj!2WPg2h@~TU(r}w_BuHH#r@qgSYB-mZ!Ya$Hi1THI zikW|g+Z4I&MYDAZy+Lg|mGy6@0-FAO2i*eRi)Ov3~+hrz3bKC*f>&G})tejx? ze>!^O=`CT{HeZ7%}Rgcp>*%VnME&i%&HqK=oM3*DrK>gx_I3t>^J( zi@v919iMLsyBK_6yk_&c>IKdOC+(pLj$)aVk83(c&)nZNDzj=ujVx&#^3BM@_npIj zKCtuwdyFyk3}1=%({9};E*@p|usf}V>dLeVLzwLI$*&? z(Dq1P*Ty9I$#Zru)*EM|B+QkQ?os8vb>hWSygFrn)~G~`MT()f&R@PwjM6SMw$v@< zqd)u6;i+q4ax)k-^@=nhPJSn=5Sqa*JRY0_+tL~aHeRiW!-s*MQXT&)Pp&_ z_FNSz5@j>JUIq0yBNScz(R7(LH4zod3a0c*`Kw0LU&daX5_>Rr!ql$0f#Ui%)AqN7 zwF&$MiIN}Ts<~17xpC~^KD_LqLIer3HEmBus1!liT1MBeucJHu`eBNR+peCu(L7xxb7@uVezXt zflWtC-r6X#)j-v3?93a2^v6eDL3tsp%6KnrPhAbA00WaV*v5Kzyg1!p0_@EFG)+{3ZCzPEL87ykcbJ@!;Gl7=qStb3Gb;(;l8RO**+!C=|8HAJz;2W@{|5+sOv2BOHojsMTLXV!1V^K6f^60jg4!SYQLTy z%E((k_3CvDt6~QB%b&Dz(C0Y12DGfESctQ_gvZ>ZYpYZMaxxgpiZ+lYwtDkaE7!`yF)am|cD`|p`0e!3Ic_qk8J zBTg!fuu81nApqyAvxrZTU^ASmY2g^Wx|Eztu&v!z2iC?lm5Ms?~hNhy(grK!*?v0R55-(?Q!{e(PD*A__U>plpoz| zWci2q$VYGWixY%XxJvrS;+5sa%Bk|hDwQl*$Owj`DwRU+R1gX)ow+41!CQRtm&M^* zdLHV9EO7~37X1a@ah?m2)Xh@CGhh?Q_kc)4|mCx3h(8r?D?H^ed3T~!3EL} z<%Ia}!pb|yYT`Tj+CrIJ?aq!-i}DUNs)fAtQPxZN^+iKHDn4IM(Mk*XKCK(Zm_g%U zop2q_y&&PGILazp^SmZINhVjXe|{>Xx;>6&H9w$GP^2}0x3Hj?ZsFB012>!eu=d)< zhB=lClm=7ZO5K-Eu9CC17aWhMSVa~O>dpr}RCaMBskU3=xN9ER^2VW;i<&zt;5{}Q zlXgi>A+-oW!kzQ@32%vpgz!SBAJt}(Ol0?9nd)gCPPx$fssE$m7ew@f$0QLJL)2Yr zZk+z{cerURXvMOlhOlLdtxl1DojYtfOF9Srw6c^ zhDv`l+)li=AgF>j8u6(o>qa$!o^`Y=X^Mq*lc30JUPX^JCHl_UU>KrT%2^Xv+min` ztMOddas$ry)iV#5XV`B+@EPk1s35*#({5FAD6wVMiA z*bGHD-7j)CJNr?+0>La(Di>rdA}VJV%+X)vZx#41Dupoek6*Dru;~_kL*4)QSEhT0^3n&&9C}pr>5n3c0 zzb?sS=~j}*8|EY{Q8hW)8bBVY_p==N6?Q@G-Q`GMn^dLbg)dO@AWe&U$DP1Vd)oGuI4av) zH%st5oUN>jA!VU@Ub6;4^fIz0LrT}-c$F)%j@&*tra!ean?`k2@>q6quBj`trc4Sa zy-Z5m@=?ALKb`y>Uzu~$$oD--)Rm3bRj7ro>5>wtnsE|pK668q8mI)_FBtRt=}aGE z#Ti}0Fy4pzW00!jokzOo@7HrYPpvfho`kqtQ~TZUxX9Moa0dSML%d9$u*XH;lSpbt zbGe)r=7tYF7g`!r^vqk57j&<;CNBhbOnWJQi^$BJ(+!(Be%eYi$TIR`Z0TB?i&yJF zD!{Wn(+xkxo6goMQQV=peEaaodRHtlQ1Af9VW<2e8S<)>aeeuWRNfn;H1dd%nH8#V zs-W^Hin-EwUX2({y2xLV-mQ)}54#Kah=c7qmt(KpB7*V1m%FlY~x``KW^?jKhdEL^iRe2`ij+^s?r?Fd-qwkF?Hj(yd zvS=-+-&2ioiIR%pjR@ReOcZ@<%%U8_iwd#CuX1!@x@OUGNxWH3!}h^_T_Y!Kf-0Gz zsbMp0nxW~ZKAS9yeeUdz#6($PO3xQnDJ38>`)uk#)qu{G%Kx-aV~vzj7cLEkla&-$2ua`}GQeo84e&r7UdHBBx?O@45l(PW}<@v?5I%g@@v z!F!@-X-F(Bv-_ZAK7@AFX(?7Ej~hPfN?ABGHw2V8#c;@0w|Ay`Bb9JA#-R&Ryp!U$ z0!L;V&ps>~?tLNtz`fWt!!aSYGB+`ScS-h{jos>JyCj!E$Vy+eB#J6Fa^a#s`k`KzO!J@TLOe&>MScg!M;O21006tw!yJRFWY@d&RfY%=-dD{o(UoL^sslwuW9 z+WPa3hm+o{7djgCV1voWXgZ9qFlRMjG}`*N!NRjoiIg6jUoZ9{rpvBzeQV5K=iG_z7!h z`nWDx=TMiALm_aA$ftg%k{qO^!a5PybNONCCRaaVU$VAS372zVVS(_^6^1=Ee#UQT zD(z#Dbu|E@&gOEXpy*Ue$^B$er3>*R?)1sf>lpz0js%%XPARF+&w+RZYQT!eZ7k|c zhz-+=?UyBrSk&dtXb=aS?Lkm{WUO`XTBBWvEcwP0#}V})Z(1=5K%qxLDxTDNG=+<{ zqiX^KQNMIahgGu9oX?b1KCMkN&5J{XUE*`Xx6r*~)ib?J+pU8VN3s7+yY}ghPz9+1 zcLy4~Qo4b1R_yet#Jl+pfjKvaL|JrLc#|)$3L#(W5}1{+%I5 z$1igDR5ijv?sQlQA-3hT<};CEi(qwuuHUh9u_+6#pLv?*RMwMwwWd*L$EMuBdTMUJ zP`&M3{Q1scv?X`!vt*jUC{9__X){jP%bMPgZ3LVDKme33zB2GBY+-u*zR?|oOIho~ zpq6ABLf(Ns0kSs*$&!y62BNCsUo5`O6^*gvCT*3TwQe^|y4N5A(ejL#N}f<8c;z^z zNDw%xZ%pnucQt3S%j7-bxj50WHiB28V+}&}++{Z&_GHPT-n({)cd4GYZ$)$-kFpOy z#54J-iCitZqC~ByiPur>d;bgdtTD@sWzvPZHy$i-_b5>%IAi)LhyMA6ho0>rY!ShF ztMRTD#u8aK{gb}MXf^r2RAwRG zf^>rBC_z=jfc4cN(IO^emUYI4`tEa;@-%P-JnA~Wn$@~Hw*ze}RbHP;!knldAN*BFxJ?kcC*Iwt876u; zc~MT&^y_EUDfg6eXsLt7x6ANe-TU$2THA81L%9&P9>sANtkiT%v`poJz;oj38eQj(Mb zlkc)QY2NiPs7W?or(Klsqoyq5xGcrS0ds_VXIW10*a(^OY5|mQpj6sdEjh4QLiccH zWf2nhGR?5tT11SPx%^BsaR4^xMer|X`%fEQY!B#ZKHk|pTzodnrf8Zugr&)${(gq2 zbBWQCca7_LIh8}8fnYgg(Ms3j@7BjT>t8w$M&SECuqW)KSj!M--NlH=M%1+S;O$XVkV$2Fn;4uaQJ>IvLJj|7t;og^8Xs{bdhfv~OT8v;IN^P? zPL%eBUA9;BWvo0R4tgfKN!m;-eYa%VAcsfrBd__Dd=PKu2-XskVrwV#J#O_UYDI+e zrs?tJR*S~pWgA^d3?EM);eS;*5&23NM)|Y3^`l(_r=8Q2w_mYWI~8$W!g^iqu9A~ZP$3;dD>nyG>IthtTw8YkJ5A{a8fXA0TtoZC??!`OhmfmFie4HywBy4sMPZc+TPIt`qwUW}lr^UABTgb# zxou_rQ(bBV3Yo%*ndsyuYxR}t^1@klvJHQ|TABLl$ax~PR(N5d80Y)x-ya!iwUZ;x zyy55yA^F}tZ;E$1ePEQFfU7{G-g6nD$Y?~--@mL;?(EeNWsCS$G*?75=E!fD&!T#4 zz?GrcMap;i8?m}is#k`yd=e_Hr_i*TF+7cl)r;3N8~wj4DK~!2u1Kj?y2$#moWN86 z;2F`?UpE#CWgQ_a8Yv(Cd=DX`daaUc2=77&7w!x$BYsYa(21+Rv*aqj>8r5(Fr~Vf z*-KXE|KjCj5LHi0*0oBFybK!CnI*~^p<%t#(2z$sOVu^p5v;UdxiVe-bDrJ(5U{~+ zBHRFBQ>^dOHE${A5S30Z3^P-!;wc`&Wu32A7mG6*6v9o=c^hj(p+M>5*UVk+J+D3O zeu7ADHLk&mM@QZ1K8elOYZ;$-)9=#lHa{9z z(nl$lMTGy}MzrrFQMdBfl{Z*DrH4!#=Ut2xQtqbojE4qsuDqj$>fL<5=*dhMxo-R> zn`%P!{tC6q#iMQk7eeF8tA`K&RR0?EFsJWUbYpKv!219cBKoCWUI4Qu`@;ygY7aWo zf-u$>;y5Wc`6+`6Q$w*3s~O|Sr;pA0ly22X%dZw&8TdQ5-+A3MVKlpldy;!0oL z-dL)ZW0`_~4x7#-rj2~Rr$_HALP{PBgQTGLhe4jM4!c zD!^XGzCLf38}^7Gpr#=t_Q#URN}ZU6@uff|c(jvUsmoE460)+pJ_Ejk><=u52g#{E zyHzY+77bJX)%BwBI4tgpjvbBEeCW6Ce&j99t6zz_3q-W-Xk>F|AeF94t7mZr3PMi{ zPIYv1Bb^Eu9!A_QKH2EVSy8%DhNH+n&`QN z`P$K!tJFf2ra!46mzCAiod@hLX=ndB`eu58imv|V?L{z+dec8Xh*dxLV3~O4G5#Pu zRq0jetq1oq$c3jm2~X$eS-ehonOUBbFw3iBbd5Z(z!ks2aSjq)V*2#P!ie6OJd*b7 zU|{p{*UOZmj~lMFa(p12%cE3x45f-!h7GG#&CcuaSU^wgwe8M5KiB>IVG~envVj8ksaIs&qK@qM z8;rQxufYwd2tX`!6D6R*gInBfCpQwUQ!;?9bsTUA~4lU_}nHu z3MHVmW7Uo1tviL%{oh<9zjuUUW1VyxIoF3j|JmIV z*8FOtg=$Q10lbIh0X=g0>#_dy6VP|mBFPbks#i>$W>lvP1#R*ok7mAHS=3{LO~cEs ztneZ$%B(KEn~;d4)1UK=EVmDV`zZt$LpB z70X)~J!bYMA{I$;)8gCO2-W+{qR(NUJNvBKp69rFv>e> z9vj8ckvfxt*=C0A>V@eexaqf}Dz3cYAQNZqzTMz>H>V+j+&tQ9uItB0S`ksV^P}ff zBNL$apeW7V=Ru97F&E)yRHB64xER3~CN_UI_&Iw(s|EH1oMLP-0xzXUi!}IXN?8nH zccSBO$AnIz&$rV`+TGuDDe$?DIy~$Bte92O9=PcNiH=Jw0~~oLC?A(S>-}~{LSRwT zv?iNfS$Im#ls{!4qEg>sM(T)T>X|xgicZLg9)xPTvNyV6V#$G|m^F{~r3tHgUZ`<^hSZ72Phei%iC)?It1vb*ow)kE;3W9LVRdkVF#&r|P;(rdk=>nJiwP zjVw7;_d!2i)~E{F;x707cP=eyx}QwMDQhxA99|)DE~_U!ckE@tmJ_KHz{nU4lk^cW<>@9%f*qKG) zm?>tA*)hh<3^6k^Gcz+YJ7#8PX67|Jw%1HCvtxElZ*$JA`)>W;tyh0lOWkUA_IYTpSY98dQ)$m>M`a}T zmfsL+P%Wxm262{i+Cy9G(c55Jv{hx*9%on$DD4V9yZ^#6=Eq9fmD@O9wMTE8b8!Fl z5MZzB8WXFw)bJUPJJwp2z`3wMy_zSyRP!BARnQ<WxA3V_u?~>+#dwMRWQKF$Q&GiuHUs@9n*Wl{MBXc*;M4X`F1h_ z#qoPjP<%%$Y|aj{Scnw0eyZaaRPO#Z)B*?}JXCIVeX)?4r8Lw6=X+2A(8xr{%rpb3 zkWEXabfgFwCcC?+UhuSUCQ?WTyb`l%H0{cU@9r{{p)qq{Z>h&j(=z3nvGl00cZk)E z%_5Ro;8N{41nKP%J&JXYmx)=Swztq?>%(vscK&)#v?`wQBrtcbzhpi}np?I*kNhhH zLgPWDH`y8Z)Mg7^EW=dXIPBPms&L+hPfAyU=j zrbjF3tSpu;9~00Iw5At1fI=N=H21M7N2ZvYZY_B^1?w}HFmCl!vUw-S7t^Tm&G+FC zhjP~~ti?TCZV#Up`RNcX?c;*5hs>-oE~ayKtSu$Hork;ZVxzjO5fz+ky5#l-f#v!O z{CLk_v6XSdE}AMMP0JO#SYvo}Dj4O?e==GHgaVm5TxIMClC;P6|B}Pz$louN&(eQ@ z+k>JoyEE8d%%}MC(U+0_Q|yuQ)Hyzlr=mPX2^z9f}j(?-6}GFZB7pKFWU-z5jmo zwCVXaG5fY5mvMMj=f7f|CD7Ibv>trh`*UmW|E%HvJhtukXHUO1zVGeosCdlJhUg84 z=mpqnJ<~TKwSM2Xtk3`P$k6w8H>Tef|Mt}3`}(jvd*WyAnU}Zs^7M3ZCGfV;N^p@U z;P+CO<>eyFCofI6q~PDO*o0G=)p2R2%i)}3a|ry>f>$fmwy3xgSGs#z9VgYX#xV(W z*x$TX&Eb6*VpNMF#ipq{1%$OUB0P`TD_n$IJSYcpafFvYQ1Flt7OrQVw{wYfaCmy$ zESlJV5kGUeu+vzd*i#digx=VbL81-X@__mjCl#7RXi!U>E1WZq#-Kp;xe{ z``aueZ0_6I+ZbPzyWAKnG(uK|{mgQ+b1^Q<*|4lv?Y**kyrAu1t84()j0!1nqzh$v zpdR{U`o1I=Y5IQTD)XivKK;4+NX$6Ietu1A>zR(Z%sAL8^8a1xY2n0pzRJ4VWwBmK z;f-zErMV6>Ljgms(?#I6z4Z{K$&)^2Nr7DYP0-t5o#&hNlEr!U7Hh1+*{UGh;a(7!*-QP2IK0tq)5{gTK)YSQX0+Pac`~04Qu@!d| z?PGl>QZ>O-{qrN+Q{3_Jsv9Eec>^YC&y%$=O+hbWlyB|3o1fsfF<)v5oHyBft~8Ht zywf9+R}J*aC`6&=o@_dy)NM_!JO@@dwLXX}?ycLF?KfLwIB#IL$OFeq7UqpX^HuZl z6kS3V;_od&R5K%@JOoUCQ(GNE$2qcPBp7v@h}QPP$35BRZdzu(ri^q={IGU8l18Bl z8tT<3@GbR1$Jks#Kf+pIMR9?-1IL&uhM_G%r?N;Id!xfT^e9l#p5!&U_n?PCp0dzhRk>%u$~ zw>N4QA(lsy9A>f0(lwgOd<36?*%e+ho*|Z-6R+6vxyiSVWG{Y<^cuH7yIIh=c+HR zuIH5if3nsx&d1cQEP$~=Q?~ay5BHu?LPMDruv?jJCR5cS zV#T;fh`{XT!Y3_gaK&}y53#%;Q;a1|2rpEQ1VVTX>J7$X*QzmmRNDkX_>d}+B_^_T z$uDXced_fI5|i?gdMu|Y<}XJyP@$CLQk+bOYn;}X7Cwr%I4^QpboI~DO;8VXmaPi8 zCqL4ybnU%@n-mAKtU0QoP@3_8-HFAkK@R+g)(wLViX3J2Vs4N)bl;8hx#boC%2Xxvc?NO)Q_c{IskAU6L~mzsi8ZlFYa zY4P)zqA@ytS^uA6+*)RQn7Z|E>O&3(%4wDzPL4*nwXcA$oN|Go(L0=0c4_Ufamohs zWId@-SJlgn{SzhvEWlj3V{mPc{SdYN^ZyRLfD<^`zpqXjWwRDNMC78=Dx9uE*&;B5 zY(Ip)UHXhF63ZfHBWZe_rE4d*q3X{-B2{9bkYsXIPJvHd4FX>C4(CdK)h(7jzP9~u ztqP!ax7sO`0@Y0(q1)GypPNtE-wS7k)xy~V_4!t12n&y!i+n{JO`(e`3t}@SD@*ci z+xGH{kd0*v_Ngclz%QDC`|H}&u4_Oy>Qwd&bt!T=b|8#$xyx30%MspLpt#&ctkw-@ z1(A-gwpDZ8H;z3M)IioUG1mB;j^jqcm^}iRoL9z|hrH3$`|l03X9L%zd`QO2*we(2 zha~%AELo=B9xfc&R|N|8Dpo^O%^r0PC$csY#nt!I@Gag>#)oqpEYH0?jtDXOQR&2S zl$&u-scAHaXm?FGPTvLGg^}dgR`+eMT<#1tyjMNLeV^*NymBjk&w8#HAZ3*vW#E2f zW7|A4DGzD80&~o)<~pM%w^(SQyj>ffC8A1pOv>7Q$cB_0+Ns%fN;KdNYpx;{EP3W- z7E7aay)B;bopWWv%c7a&(0-x{QqTA@668L}z#*bv$~XpbZ)V)os!Mu$0pTi*RDf_% z5IZ+ATX0&O6Oltle<>->Ja+!~@mCbLI9h@IoO~-=d%bYP%~o9wDCrq{7g{|7036Gk z^fqN}d}XPb0U&bWbu&h`KQSvaklbTat^+r$>N72@LkCe|JUCh3LfuYF+BDm#Eoz2rPI zSq7`StWs?9qjRL}HIGlU)jETG#e?Tn+-Fm@c$B zWJy?q-4H7`JEKR@MEFw}$M{^y4dKvo|$6%gW#*|MM0 zFsLsEAs7~|lCiXT-8a0KwdpFY22$f7e7f@{ILE)df7DCEc@o*}z2Fx`AK%JvHCygf zqVp%K?#Z#n8*G?tquYk&*OA;7B)4o(Jq1rs=vNQ9#ux+t2cDZMA+8kL2If#`6hcOyZ`=PC++^>=Fd*$I98!Blgj^YTopq|`pEi$xZa!(LwW zBE2GonKDBzmu+CF>O{>YVVZ|pbL&t z9N34RSe@DYTlLkis>Vq->K9Zr{+L`e{!1I0&)SBmv_0Tb^1G`PG>qF)4!A%){&kh- zSXI%PxE=VcnBjR$E}kHJr_*B-kZtJg30ZZ}xYjvH|JBi#jk~I*fo%Am#txkuejx~d zfP<^12J~p!Rr9;Hcr;^w$i%slgLf_ps>ciN2xSnIw2kS;QLD%8rR>jTl)Q}16My1y zE9+rWahbD`Z)GedOVMk}R*0FimEh(qC9m`rr+l(jv9h-LbHkJ#!(T1dqy~;px^E1! zJ8B?TGWVV7QKhq{EK5=XY^JoF)}-=*ehX3o@?;g?Xu|YrGtr17m6R*zHEF>36Epd) zeyV}9c><*ZG_`@jlmb(|3u@rBsiu4=zil3xWwhZOf=Fs0LpCgaHQ6A?UxwW_rvymY z;)IsgKyvn3CN)yjKw7zgN>2-F!7Yw%HKVC$giF&5$jWKMQPVQ0Pm$-DMUj9W3lpgG zQ!0QmO%0s+4`X$Y4S7Gm&k6>={Qi?Tnhj(4^sifyIDay@*4Om$-5TyQIdrb~cJNxW zDCtX({(xCCN_xSNCQ-#fRv!tg0#ViXe5j}BsX@XC2H&Ex4Zmsp)f-<@h2Vewt2HDW zFlfsca=u;FV;r1(Ni8%|2`kz8)Xt0kRcn%k>tCJmxgbu63#2s6G$v%_K=LgI;g4%y zQqh7KMwCuDGBfCDO9s5of4T>s+>~4%I?ssT?mk{n+p(eki?KjBhw7iY$6GP<-ejf{ zVxKCtmr`B9Y5#mmVQw$=&FP_3<-Uf7zJ9y91e2Rkm!>HIbEN=D-C!*H5#Z83_{3p% z2B_i^JfW_~GaD-6Mq44_ps5!osO?8`Z3pM^>l6d$Ssc`)v$oFi|*=&SD0SB&I z79XkJy={3Dn?^jJPVha3FcKBOZhUva%gu@AY;~n!n|-3=&UU9IYnn62QV+PmsH6&7 z2fYgV4nnZ+)M)S+;=edH;EM%xw_(jtLM|u2Xx^gs$sgG zo4I(n4apJaN0?DOI$lZn;#Sv_*RyFK_&!Y4JtK{6RK>Hx@9+XZEX6E@e_tKe0w!B3*b3Q4fSs z(@lJN!Gv+FXYtHNhGn#AU{ z#;CB^KIZ8Pa{i!Z8ANV%k&SgNEBIqng;Oc;!;RgUO=slFF7tFg1=R77XFSi7J|T98 z@nj7DgS~$YlX?`P|Lt40aG&AzfXptTF|{e0 z{oDlkNXsVyTvtga3Uev-59pm}$+a^GLpD*h26m9T1Kb!cP-hBrn6z+$>h)NVx{B33 zLh7%|`5c;anEE!itDPSzb>pf@$}S~CqYeg#gjUJF$j zb=irQxA3tmPajV&A5O<1@xl5SZ`#l%+iglsFPjySGar>kBKv;JlN@D~5mFTXh@Per z>NP~qxyHW|yZuqa3|zBwjtiJh2N(xW0&X(YkXSrDQh&-2cEZjGF4w{&X<6fKY80&+ zH$|>h!MMJ}GJjkjDzb5XcTapY{PY^76Lk*8IRDY(_T-6Tx8IujO_MREA5GJWK|PB>AB=>4;M2xyJv1#J?7L2R@g@>OT<4m1cpXQIv1` zL1Do~^?xDKycT2`HREG659`DZn&pO7UGIs4BDZt16|ZMEn~Z045hZly zdmdE(*hCbhAe#u;)CAN9|H*jV^RO5zH)^Oh1w-0wB5efXJvm)=im}$1RNs_oHJtUQK5NiHDOz6jg_<+!E(D@sawv1;+ezecAJ!eqs2+uzA$$#NE9j^ zFeN}F&H%QNfUhwk+Z%MFIc(+v!~zC2Bz8;&OeAeEOULIh`!LmP#T=5cNXI7tjikdO zuu0;RXuNuiAKR~AuGgcx&5OtVE|gYBA$9PsyW#_^qq19MjWVLOshoi9k`z}yH+B^M zk%F!oFSX6_#tJLbYHMRmR0ragAXL6n9B)Z9mhT{<`4_3QPcTy9BdGrspdCwjaQqBE z=~&{6AFPDu409&+!Z^N2nd9RCq)1tly6KG;+-;}FN&ae%gVCDzS2*gt#7;&bNH7%C zmT+OVhoJj0cm@>3UU9=`hs4@3f^l&uPFb&`v1y#b1b+aIWa47Qxtu;*IsAVi>c1Kh zG#lq%2>rJa;VeGUL*L&!t_u*69e#R&8^(oBtiT!ieu|-uBeApOkYc1z4_Am+%WJ>{ zzdp~Z^Zdt9ZuE9A-@reFH;vU`J%Tq)go1%534}v9=w``(0IF1rC!-(L(z_q+LfQE| znIo@?7Gh;5GkN0UYZx<#UUD7YaXvU{IT=|gDP|1^z(`6kK}m^!zU-cNug9aKBTz83 zP*Lq%MMXYOUxcl)3Jhy$prQ&pk4!L4A~)cZ3y@iJ3~6N&8C6L7Nl*}Fw@8*yJR2$i zl>KmIMi0ZIvJb*n{Ky1`p}#(ptWKs7K@0Nr2Qj|VX`m3XEAb6otD918pM7*{3cMO^ zo^p2YE2V>}o~7(&lwTNdqgo(&hp~DX<}?RqMtAQQ0w1V^8j`~Gr!HM?oXvCR`dCJAWJcdydeqabShrW-os$i(C# z2FfPwE%nGILDYBQIi2e?;UVl~YVx#?-18Dn2r%@3*0%3;qP#EH6Hh!iH7N-CLMF*hYs{ zrR9(8&sNF5HYV643DoibUjN>x_NwZtC&e>cuz$94fi|Xc`ZvgYDE*LK z!?a#)^I`5(GXqO(HYSkzDaZM@V@rGh_10~#`7T+bG)@n6M9!q!Hw{SSmSfz>#RSqq ziEh&4@%n-nc>Zf%mWeo0~9 z)UWeMcsZIbb$-CeU;2xDf{n0&c>dB$#-4i`XmIHxIba&) zKfeTwe7%Q4m0mwtn;up5cPv~7G?B?Q9G+DUXg0x!Nr2V#8k+~?_;@w4!5lgJ&eGlw z&=I>SsRILsRl2?q_)Q#k?y(tyb!>pw(lHdv>5$lkwK&k23w$}c2{;|b{ACD4YEvGj zW3(=r14x%8<)uj4c0lQMWdej{m$`E`PIz2~(_4fYcmLSQZ5QN?!m_ar*abHLA5&%C z4IbNTu|C3yCQA-Pe*|xW9xN4`x1+gx2XOGMJkt8l8FsIolaEAogYTs8U?h!kgEuTk zwMYEqrSn{@>d^D#gomHnk7}U~fMuvt(gOSeMH%JNS<#MV|`B<0qvK)DS$4$;=4Hq{iwmd<*!%ZHE zRHvNixJ9|J>na7>f8)?y?&54`8Txt2y{+-Bt}u6dg%L0EWx`z7TwWLZ za&do|cgG-tf)bRwZ)z-LTPR4CN>S>SBus8b5f2-3z}tOpRE#w{oiyQtuW~qKL95rf zTCrGaNT<{JW5=nEfPV8lQi$lh*Z=Kt|7YyiBe(4z_d2j4ggH8$iu>n3WB(E))h*Kw zxw@V6MM=^eUM@~2Vo4yv#CY^7u@G-dF2&;Z7as=HFWEObv+4nh1gOKJ=o{M0$&tJf#9ha1%pvi>Pq*~(WE!m_?|`r{YMQ}W5BFmlCJKf z#>#$KN_tXM0^p4o;tDCI|w&L
4zj@biEr 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

6#Q>a+p_Z}C%$4fKm0Gkg}EZ61C38WK(Ya+ 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�c3hU~AQ+mqHax83+Q9V!E8 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 Il(dxp1C7>@@Bjb+ literal 0 HcmV?d00001 From f30461421f623f3dfd0d7c0c6f11bb5c30a98ec9 Mon Sep 17 00:00:00 2001 From: Foppe Hemminga Date: Tue, 23 Dec 2014 10:39:52 +0100 Subject: [PATCH 196/199] Added Docs section to README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 92c53d6d..bf872c22 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,9 @@ DDS tries to figure out the available number of cores and the available memory. 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. Bugs ==== From 3d6e7d0729bf7f505f3b42d5d204fed42f248a51 Mon Sep 17 00:00:00 2001 From: Soren Hein Date: Mon, 5 Jan 2015 14:59:26 +0100 Subject: [PATCH 197/199] Makefiles for Windows with Windows-like make --- examples/Makefiles/Makefile_Visual_Windows | 151 +++++++++++++++ src/Makefiles/Makefile_Visual_Windows | 154 +++++++++++++++ test/Makefiles/Makefile_Visual_Windows | 209 +++++++++++++++++++++ 3 files changed, 514 insertions(+) create mode 100644 examples/Makefiles/Makefile_Visual_Windows create mode 100644 src/Makefiles/Makefile_Visual_Windows create mode 100644 test/Makefiles/Makefile_Visual_Windows diff --git a/examples/Makefiles/Makefile_Visual_Windows b/examples/Makefiles/Makefile_Visual_Windows new file mode 100644 index 00000000..5fffb150 --- /dev/null +++ b/examples/Makefiles/Makefile_Visual_Windows @@ -0,0 +1,151 @@ +# This is a Makefile for the examples, +# for Windows and the Microsoft Visual C++ compiler. +# Contributed by Philippe Capron in December 2014. + +# Unlike the other Makefiles, it does not assume Unix-like commands. + +# The test program itself does not use multi-threading, +# but the DLL might, depending on how it was compiled. + +# 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 + +COMMON_SOURCE_FILES = \ + hands.cpp + +ALL_EXAMPLE_FILES = \ + AnalysePlayBin.cpp \ + AnalysePlayPBN.cpp \ + AnalyseAllPlaysBin.cpp \ + AnalyseAllPlaysPBN.cpp \ + CalcDDtable.cpp \ + CalcDDtablePBN.cpp \ + CalcAllTables.cpp \ + CalcAllTablesPBN.cpp \ + DealerPar.cpp \ + Par.cpp \ + SolveBoard.cpp \ + SolveBoardPBN.cpp \ + SolveAllBoards.cpp + +OBJ_FILES = \ + hands.obj + +EX_OBJ_FILES = \ + AnalysePlayBin.obj \ + AnalysePlayPBN.obj \ + AnalyseAllPlaysBin.obj \ + AnalyseAllPlaysPBN.obj \ + CalcDDtable.obj \ + CalcDDtablePBN.obj \ + CalcAllTables.obj \ + CalcAllTablesPBN.obj \ + DealerPar.obj \ + Par.obj \ + SolveBoard.obj \ + SolveBoardPBN.obj \ + SolveAllBoards.obj + +EX_EXE_FILES = \ + AnalysePlayBin.exe \ + AnalysePlayPBN.exe \ + AnalyseAllPlaysBin.exe \ + AnalyseAllPlaysPBN.exe \ + CalcDDtable.exe \ + CalcDDtablePBN.exe \ + CalcAllTables.exe \ + CalcAllTablesPBN.exe \ + DealerPar.exe \ + Par.exe \ + SolveBoard.exe \ + SolveBoardPBN.exe \ + SolveAllBoards.exe + +AnalysePlayBin: $(OBJ_FILES) AnalysePlayBin.obj + link /LTCG $(OBJ_FILES) $(DLIB) AnalysePlayBin.obj /out:AnalysePlayBin.exe + +AnalysePlayPBN: $(OBJ_FILES) AnalysePlayPBN.obj + link /LTCG $(OBJ_FILES) $(DLIB) AnalysePlayPBN.obj /out:AnalysePlayPBN.exe + +AnalyseAllPlaysBin: $(OBJ_FILES) AnalyseAllPlaysBin.obj + link /LTCG $(OBJ_FILES) $(DLIB) AnalyseAllPlaysBin.obj /out:AnalyseAllPlaysBin.exe + +AnalyseAllPlaysPBN: $(OBJ_FILES) AnalyseAllPlaysPBN.obj + link /LTCG $(OBJ_FILES) $(DLIB) AnalyseAllPlaysPBN.obj /out:AnalyseAllPlaysPBN.exe + +CalcDDtable: $(OBJ_FILES) CalcDDtable.obj + link /LTCG $(OBJ_FILES) $(DLIB) CalcDDtable.obj /out:CalcDDtable.exe + +CalcDDtablePBN: $(OBJ_FILES) CalcDDtablePBN.obj + link /LTCG $(OBJ_FILES) $(DLIB) CalcDDtablePBN.obj /out:CalcDDtablePBN.exe + +CalcAllTables: $(OBJ_FILES) CalcAllTables.obj + link /LTCG $(OBJ_FILES) $(DLIB) CalcAllTables.obj /out:CalcAllTables.exe + +CalcAllTablesPBN: $(OBJ_FILES) CalcAllTablesPBN.obj + link /LTCG $(OBJ_FILES) $(DLIB) CalcAllTablesPBN.obj /out:CalcAllTablesPBN.exe + +DealerPar: $(OBJ_FILES) DealerPar.obj + link /LTCG $(OBJ_FILES) $(DLIB) DealerPar.obj /out:DealerPar.exe + +Par: $(OBJ_FILES) Par.obj + link /LTCG $(OBJ_FILES) $(DLIB) Par.obj /out:Par.exe + +SolveBoard: $(OBJ_FILES) SolveBoard.obj + link /LTCG $(OBJ_FILES) $(DLIB) SolveBoard.obj /out:SolveBoard.exe + +SolveBoardPBN: $(OBJ_FILES) SolveBoardPBN.obj + link /LTCG $(OBJ_FILES) $(DLIB) SolveBoardPBN.obj /out:SolveBoardPBN.exe + +SolveAllBoards: $(OBJ_FILES) SolveAllBoards.obj + link /LTCG $(OBJ_FILES) $(DLIB) SolveAllBoards.obj /out:SolveAllBoards.exe + +%.obj: %.cpp + $(CC) $(CC_FULL_FLAGS) /c $< /Fo$*.obj + +clean: + del $(OBJ_FILES) $(EX_OBJ_FILES) $(EX_EXE_FILES) $(DLL) $(DLIB) + + + +# DO NOT DELETE + +CalcDDtable.obj: ../include/dll.h hands.h +CalcDDtablePBN.obj: ../include/dll.h hands.h +CalcAllTables.obj: ../include/dll.h hands.h +CalcAllTablesPBN.obj: ../include/dll.h hands.h +DealerPar.obj: ../include/dll.h hands.h +Par.obj: ../include/dll.h hands.h +SolveBoard.obj: ../include/dll.h hands.h +SolveBoardPBN.obj: ../include/dll.h hands.h +SolveAllBoards.obj: ../include/dll.h hands.h diff --git a/src/Makefiles/Makefile_Visual_Windows b/src/Makefiles/Makefile_Visual_Windows new file mode 100644 index 00000000..10fa8095 --- /dev/null +++ b/src/Makefiles/Makefile_Visual_Windows @@ -0,0 +1,154 @@ +# 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/test/Makefiles/Makefile_Visual_Windows b/test/Makefiles/Makefile_Visual_Windows new file mode 100644 index 00000000..2c74d36c --- /dev/null +++ b/test/Makefiles/Makefile_Visual_Windows @@ -0,0 +1,209 @@ +# 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 From 6dd732a1bcbe7cd0db701f3b3a1a7fc6c48b3ef9 Mon Sep 17 00:00:00 2001 From: Soren Hein Date: Mon, 5 Jan 2015 16:04:42 +0100 Subject: [PATCH 198/199] Cumulative update to documentation text files --- ChangeLog | 21 +++++++++++++++++++++ INSTALL | 15 +++++++++++++-- README.md | 2 +- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 65baf2f6..bb8fe601 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +Release Notes DDS 2.8.1 +----------------------- +Added Makefile for shared library (.d) under Linux. Contributed +by Foppe Hemminga and Paul Hide. + +Added Makefile for Visual C++ using Windows command-line tools, +so the Windows make and no "mv" etc. Contributed by Philippe Capron. + +Fixed bug in scheduler that caused some hands to be considered +identical when they aren't. Alexis Maugat found the bug and +contributed a simple test case. + +Fixed bug in initialization that affected some cases when initial +moves are given. Alexis Maugat found the bug and contributed a +simple test case. + +Added in Foppe Hemminga's version of the documentation, written +entirely in .md markup format (looks great on Github) and capable +of being converted into html and pdf. + + Release Notes DDS 2.8.0 ----------------------- 2.8.0 is about 15% faster than 2.7.0. diff --git a/INSTALL b/INSTALL index ada493b6..fc02e1b4 100644 --- a/INSTALL +++ b/INSTALL @@ -67,12 +67,17 @@ local install to ../lib, not a system-wide one). System-specific data ==================== -Microsoft Visual C++ +Microsoft Visual C++ (Unix-like, so Cygwin and mingw) -------------------- Makefile: Makefile_Visual Compiler: cl +Microsoft Visual C++ (Windows-like, so no "mV", different "make") +-------------------- +Makefile: Makefile_Visual_Windows +Compiler: cl + Mingw ----- Makefile: Makefile_mingw @@ -85,12 +90,18 @@ Makefile: Makefile_cygwin Compiler: g++ -Linux +Linux (static library .a) ===== Makefile: Makefile_linux Compiler: g++ +Linux (dynamic library .ld) +===== +Makefile: Makefile_linux_shared +Compiler: g++ + + Apple ===== Makefile: Makefile_Mac_clang (for clang compiler, single-threaded) diff --git a/README.md b/README.md index bf872c22..9a730237 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Alex Martelli cleaned up and ported code to Linux and to Mac OS X in 2006. The Brian Dickens found bugs in v2.7 and encouraged us to look at GitHub. He also set up the entire historical archive and supervised our first baby steps on GitHub. -Foppe Hemminga maintains DDS on ArchLinux. +Foppe Hemminga maintains DDS on ArchLinux. He also contributed a version of the documentation file completely in .md mark-up language. Soren Hein made a number of contributions before becoming a co-author starting in v2.8 in 2014. From 6a8d1a2863573e31895c3eedfbe9019022cfc467 Mon Sep 17 00:00:00 2001 From: Soren Hein Date: Mon, 5 Jan 2015 15:58:19 +0100 Subject: [PATCH 199/199] Fixes bugs in LastTrickWinner Was returning wrong result when only one trick was input. --- src/SolverIF.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SolverIF.cpp b/src/SolverIF.cpp index 8457c8d0..e30c83c3 100644 --- a/src/SolverIF.cpp +++ b/src/SolverIF.cpp @@ -1103,7 +1103,7 @@ void LastTrickWinner( { hp = handId(dl->first, h); lastTrickSuit[hp] = dl->currentTrickSuit[h]; - lastTrickRank[hp] = dl->currentTrickRank[h]; + lastTrickRank[hp] = bitMapRank[dl->currentTrickRank[h]]; } for (h = handRelFirst; h < DDS_HANDS; h++) @@ -1157,8 +1157,8 @@ void LastTrickWinner( } } - * leadRank = lastTrickRank[handRelFirst]; - * leadSuit = lastTrickSuit[handRelFirst]; + * leadRank = highestRank[maxRank]; + * leadSuit = maxSuit; * leadSideWins = ((handToPlay == maxHand || partner[handToPlay] == maxHand) ? 1 : 0); }