Bo Haglund, Bob Richardson
Rev S, 2014-01-18
Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/


Short description of the DLL functions supported in Double Dummy Problem Solver 2.4.2

Callable functions

extern "C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target,  
    int solutions,  int mode, struct futureTricks *futp, int threadIndex);

extern "C" __declspec(dllimport) int __stdcall SolveBoardPBN(struct dealPBN, int target,  
    int solutions,  int mode, struct futureTricks *futp, int threadIndex);

extern "C" __declspec(dllimport) int __stdcall CalcDDtable(struct ddTableDeal tableDeal, 
    struct ddTableResults * tablep);

extern "C" __declspec(dllimport) int __stdcall CalcDDtablePBN(struct ddTableDealPBN
    tableDealPBN, struct ddTableResults * tablep);

extern “C”__declspec(dllimport) int __stdcall CalcAllTables(struct ddTableDeals *dealsp,
    int mode, int trumpFilter[5], struct ddTablesRes *resp, struct allParResults*presp);

extern “C”__declspec(dllimport) int __stdcall CalcAllTablesPBN(struct ddTableDealsPBN
    *dealsp, int mode, int trumpFilter[5], struct ddTablesRes *resp, 
    struct allParResults *presp);

extern "C" __declspec(dllimport) int __stdcall SolveAllBoards(struct boardsPBN *bop,
    struct solvedBoards *solvedp); 

extern "C" __declspec(dllimport) int __stdcall CalcPar(struct ddTableDeal tableDeal, int vulnerable, struct ddTableResults * tablep, struct parResults *presp);

extern "C" __declspec(dllimport) int __stdcall CalcParPBN(struct ddTableDealPBN tableDealPBN, 
  struct ddTableResults * tablep, int vulnerable, struct parResults *presp);            


SolveBoard

SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. The actual maximum number is configured at initial start-up, this number is maximum 16. 

Before SolveBoard can be called, a structure of type "futureTricks" must be declared. 

SolveBoard returns a status integer, "no fault" means the DLL supplies the trick data in the "futureTricks" type structure.
Status codes:   
   1=No fault, 
  -1=Unknown fault, 
  -2=No of cards = 0, 
  -3=target > Number of tricks left,                         
  -4=Duplicated cards, 
  -5=target < -1, 
  -7=target >13, 
  -8=solutions < 1, 
  -9=solutions > 3, 
-10=No of cards > 52
-11=Not used
-12=Suit or rank value out of range for deal.currentTrickSuit or deal.currentTrickRank.
-13=Card already played in the current trick is also defined as a remaining card to play.
-14=Wrong number of remaining cards for a hand.
-15=threadIndex < 0 or >=noOfThreads, noOfThreads is the configured maximum number of threads.
  
Structure ”deal” defines all data needed to describe the deal to be analyzed.
struct deal { 
   int trump;   /* I.e. which suit that is trump or if contract is NT, Spades=0, Hearts=1, Diamonds=2, Clubs=3,  NT=4 */ 
   int first;      /* 0-3, 0=North, 1=East, 2=South, 3=West , Leading hand for the trick.*/ 
    int currentTrickSuit[3];  /* 0-2 for up to 3 cards in the order played */
   int currentTrickRank[3];  /* 2-14 for up to 3 cards */
   unsigned int remainCards[4][4]; /* 1st index hand (0-3), 2nd index suit (0-3), values as bitstring of ranks bit 0=0, bit 1=0, bit 2=rank 2, ………. bit 14=rank 14, bit 15=0 for cards remaining after already played cards (cards already played to the current trick are not included in this bitstring).  
 The decimal value for a card then range between 4 (=rank 2) and 16384  (Ace=rank 14). */ 
}; 

Parameter ”target” is the number of tricks to be won by the side to play, -1 means that the program shall find the maximum number. For equivalent  cards only the highest is returned. 

Parameter ”solutions” defines how many card solutions that SolveBoard must return:
  target=1-13, solutions=1:  Returns only one of the cards. Its returned score is the same as target when target or higher tricks can be won. Otherwise, score –1 is returned if target cannot be reached, or score 0 if no tricks can be won. 
  target=-1, solutions=1:  Returns only one of the optimum cards and its score.
  target=0, solutions=1:  Returns only one of the cards legal to play with score set to 0.
  target 1-13, solutions=2:  Return all cards meeting target. Their returned scores are the same as target when target or higher tricks can be won. Otherwise, only one card is returned with score –1 if target cannot be reached, or score 0 for all cards legal to play if no tricks can be won.
  target –1, solutions=2:  Return all optimum cards with their scores.
  target=0, solutions=2:  Return all cards legal to play with scores set to 0.
  target irrelevant, solutions=3:  Return all cards that can be legally played with their scores in descending order.

Parameter ”mode” defines the DLL mode of operation.
  mode=0:  Do not search to find the score if the hand to play has only one card, including its equivalents, to play. Score is set to –2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don’t always search to find the score.  
  mode=1:  Always search to find the score. Even when the hand to play has only one card,  with possible equivalents, to play.  For both mode=0 and mode=1: If the preceding SolveBoard call had the same trump suit and the same deal, except for deal.first, then the transposition table contents is reused from the preceding SolveBoard call. Setting mode=2 is no longer needed in this case, but can still be done for backwards compatibility.
  mode=2:  As for mode=1, but the transposition table contents is reused from the preceding SolveBoard call. It is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. 
1st call:  SolveBoard(deal, -1, 1, 1, &fut, 0),  deal.first=1, i.e. East leads.
 	2nd call:  SolveBoard(deal, -1, 1, 2, &fut, 0),  deal.first=2, i.e. South leads.
 	3rd call:  SolveBoard(deal, -1, 1, 2, &fut, 0),  deal.first=3, i.e. West leads. 
4th call:  SolveBoard(deal, -1, 1, 2, &fut, 0),  deal.first=0, i.e. North leads.   

struct futureTricks { /* The DLL provides the score (number of tricks) that can be won by the card to play defined by its suit and rank. Array of all alternative cards. */ 
  int nodes;     /* Number of searched nodes */
  int cards;         /*  No of alternative cards  */
  int suit[13];         /* 0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs */
  int rank[13];        /* 2-14 for 2 through Ace */ 
  int equals[13];        /* Bitstring of ranks for equivalent lower rank cards. The decimal value range between 4 (=2) and 8192 (King=rank 13).  When there are several ”equals”, the value is the sum of each ”equal”. */
  int score[13];     /* -1 indicates that target was not reached, otherwise target or max numbe of tricks */ 
} ; 

Parameter ”threadIndex” defines the identity of the thread used when calling SolveBoard.
A configured maximum number of threads can call SolveBoard in parallel, threadIndex must be an integer in the range 0..max number of threads - 1. This maximum number is configured at DLL initial start-up and cannot exceed 16.


SolveBoardPBN

In SolveBoardPBN the remaining cards in the deal information are given in PBN text
format (e.g. 
W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K) instead of using bits 2-14 in an integer array. Otherwise, SolveboardPBN is identical to SolveBoard.

struct dealPBN {
   int trump; 
   int first; 
   int currentTrickSuit[3];  
   int currentTrickRank[3];  
   char remainCards[80];   /* First character identifies the hand having the cards given first
                                         in the string, then the cards of the other hands are given in a
			     clock-wise order, see example above. Null characters fill out
			     the character array at the end. */ 
};


CalcDDtable

CalcDDtable calculates the double dummy values of the initial 52 cards for all the 20 trump suit/declarer hand combinations.   

Before CalcDDtable can be called, a structure of type " ddTableResults" must be declared.
CalcDDtable returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure.
Status codes:   
   1=No fault,
   Other status codes are errors, with codes equal to SolveBoard status codes.   

Structure ”ddTableDeal” defines the dealt cards to be analyzed.
struct ddTableDeal {
  unsigned int cards[4][4];   /* 1st index is hand, 2nd index is suit, same coding as for deal.remainCards for SolveBoard. */
};

struct ddTableResults { /* For each combination trump suit / declarer hand, the DLL provides the double dummy score. */
  int resTable[5][4];	/* 1st index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No Trump 2nd index is declarer hand, 0=North, 1=East, 2=South, 3=West */
};


CalcDDtablePBN

In CalcDDtablePBN the remaining cards in the deal information are given in PBN text format, see the description above for SolveBoardPBN. Otherwise, CalcDDtablePBN is identical to CalcDDtable.

struct ddTableDealPBN {
  char cards[80];
};


CalcAllTables

CallAllTables calculates the double dummy values of the trump suit/declarer hand combinations for a number of DD tables in parallel. This increases the speed compared to calculating these values using a CalcDDtable call for each DD table.

The maximum number of DD tables in a CallAllTables call depends on the number of strains (the number of 5 trump alternatives, any of the 4 suits and no trump) to be part of the DD calculations. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher:
4 strains maximum 12 DD tables
3 strains maximum 16 DD tables
2 strains maximum 25 DD tables
1 strain maximum 50 DD tables

Before CalcAllTables can be called, a structure of type "ddTablesRes" must be declared.
CallAllTables returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTablesRes" type structure. Its contained structure of type “ddTableResults” is described for the function CalcDDtable. The variable “noOfBoards” shows the number of solved boards (max 200).

struct ddTablesRes {
  int noOfBoards;
  struct ddTableResults results[MAXNOOFBOARDS / 4];
};

Status codes:   
   1=No fault,
   -201=Error, all trump suits and the no trump suit alternative have been marked in the
       calling parameter trumpFilter to be left out (i.e. they have all been set to TRUE),
   -202=Error, too many DD tables in the call.

Structure “ddTableDeals” contains up to 50 DD table deals, each in a structure “ddTableDeal”, 
described for the function CalcDDtable. The actual number is set in the “noOfTables” parameter.

struct ddTableDeals {
  int noOfTables;
  struct ddTableDeal deals[MAXNOOFBOARDS / 4];
};

Parameter “mode” specifies whether or not par score and par contracts will be calculated
and if so, which sides that are vulnerable:
-1:    no par calculation
0:	par calculation, vulnerability None
1:	par calculation, vulnerability All
2:	par calculation, vulnerability NS only
3:	par calculation, vulnerability EW only

The results of the par calculations are given in the structure “allParResults”,
which contains the results for all boards. Each board results are given
in structure “parResults”, described for the CalcPar function.

struct allParResults {
  struct parResults presults[MAXNOOFBOARDS / 4];
};

Parameter “trumpFilter” describes which, if any, of the trump suits or the no trump suit
alternatives that will be excluded from the calculations. They are defined in the order Spades, Hearts, Diamonds, Clubs and No Trumps. E.g. setting trumpFilter to {FALSE, FALSE, TRUE, TRUE, TRUE} means that values will only be calculated for the trump suits Spades and Hearts.


CalcAllTablesPBN

As for CalcAllTables except that the deals are given in PBN format. The structure
“ddTableDealPBN” is described for the CalcDDtablePBN function.

struct ddTableDealsPBN {
  int noOfTables;
  struct ddTableDealPBN deals[MAXNOOFBOARDS / 4];
};


SolveAllBoards

SolveAllBoards solves a number of boards in parallel for increased performance compared to solve them sequentionally using a SolveBoard call for each board.

SolveAllBoards is called with a buffer containing board data for a number of boards, maximum 200 boards per call. Each board is defined with the same input data as in SolveBoardPBN. The input data per board can be freely given independent of the settings for the other deals. SolveAllBoards uses multi-thread calls to SolveBoardPBN for solving the buffered boards.

struct boardsPBN {
  int noOfBoards;
  struct dealPBN deals[MAXNOOFBOARDS];
  int target[MAXNOOFBOARDS];
  int solutions[MAXNOOFBOARDS];
  int mode[MAXNOOFBOARDS];
};

struct solvedBoards {
  int noOfBoards;
  struct futureTricks solvedBoard[MAXNOOFBOARDS];
};

In the SolveAllBoards call, the cards are coded in PBN text format using the dealPBN structure. The number of boards to be solved must be defined in the boardsPBN structure, the number must not exceed MAXNOOFBOARDS which is 200. In the returned information in struct solvedBoards, the number of solved boards are given. The futureTricks information is provided for all solved boards with the same returned information per board as with SolveBoard. 

SolveAllBoards returns 1 if the call succeeds, otherwise an error code identical to the SolveBoard error codes is given when there is a problem in the input information.

Notes on DDS use for simulations

SolveAllBoards is optimal when the input boards are dissimilar. Adjacent boards in the boards buffer that are similar (same trump, very minor difference between cards distribution between hands) typically means that transposition table information cannot be reused. That is because these boards typically use different threads. In simulations involving different declarer hand alternatives and possibly also different suit trump alternatives, usage of CalcAllTables is a more convenient and probably a faster alternative. 
E.g. if the task is to make simulations to find which of the major suits is best in a trump contract and which hand is best as declarer, then such simulation is easily set up using CalcAllTables and most likely runs faster than with SolveAllBoards.

CalcPar

CalcPar calculates the par score and par contracts of a given deal. It also includes calculation and presentation of the double dummy values table otherwise calculated by the CalcDDtable function, since this table is a prerequisite for the par calculations. Thus there is no need to make a CalcDDtable call before calling CalcPar. 

Before CalcPar can be called, a structure of each type " ddTableResults" and “parResults” must be declared.
CalcPar returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure and the par results in the “parResults” structure.
Calling CalcPar with the structure of type “ddTableDeal” is done in the same way as for calling CalcDDtable.

Status codes:   
   1=No fault,
   Other status codes are errors, with codes equal to SolveBoard status codes. 

Parameter “vulnerable” is set according to:
0 = None
1 = Both sides
2 = North / South side vulnerable
3 = East / West side vulnerable

The structure types “ddTableDeal” and “ddTableResults” are described for the function CalcDDtable. 
The “parResults” structure type includes the par score and the par contracts results returned by the call to CalcPar:

struct parResults {
  char parScore[2][16];	/* index = 0 is from NS view and index =1 is from EW view. */
  char parContractsString[2][128]; /* index = 0 is NS view and index = 1 is EW view. By “view” is
       here meant which side that starts the bidding. */
}; 

Par score is given as a text string, e.g NS -460. NS lost 460 points. 
All par contracts for different suits are listed with comma separating the suits.
Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in No trumps, are given as 345N.

Example of par contracts in different suits:
NS:NS 23S,NS 23H
This is from the NS view. North and South as declarer make 2 or 3 Spades and Hearts contracts, 2 Spades and 2 Hearts with an overtrick.
If only North could make 3 Hearts, the text string would have looked:
NS:NS 23S,N 23H  
NS before the colon refers to the assumed side that made the initial bid in the process for determining the par score / contracts. 
Also, DDS calculates the par score / contracts when the assumed side is EW:
EW:NS 23S,N 23H  
Nearly always, the par score / contracts are the same for both starting points. One case where they are not is if both sides can make 1 NT but no other contract. 


CalcParPBN

The only difference compared to CalcPar is that the structure type “ddTableDealPBN” is used instead of “ddTableDeal”. For description of “ddTableDealPBN”, see CalcDDtablePBN. 
  


Revision History

Rev A, 2006-02-25.		First issue.

Rev B, 2006-03-20		Updated issue.

Rev C, 2006-03-28	Updated issue. Addition of the SolveBoard parameter ”mode”.

Rev D, 2006-04-05	Updated issue. Usage of target=0 to list all cards that are legal to play.

Rev E, 2006-05-29	Updated issue. New error code –10 for number of cards > 52.

Rev F, 2006-08-09	Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters.

Rev F1, 2006-08-14	Clarifications on conditions for returning scores for the different combinations of the values for target and solutions.

Rev F2, 2006-08-26	New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank.

Rev G, 2007-01-04	New DDS release 1.1, otherwise no change compared to isse F2.

Rev H, 2007-04-23	DDS release 1.4, changes for parameter mode=2.

Rev I, 2010-04-10	DDS release 2.0, multi-thread support.

Rev J, 2010-05-29	DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals.

Rev K, 2010-10-27	Correction of fault in the description:  2nd index in resTable of the structure ddTableResults is declarer hand.

Rev L, 2011-10-14	Added SolveBoardPBN and CalcDDtablePBN.

Rev M, 2012-07-06	Added SolveAllBoards. 

Rev N, 2012-07-16	Max number of threads is 8.

Rev O, 2012-10-21	Max number of threads is configured at initial start-up, but never exceeds 16. 

Rev P, 2013-03-16	Added functions CalcPar and CalcParPBN.

Rev Q, 2014-01-09	Added functions CalcAllTables/CalcAllTablesPBN. 

Rev R, 2014-01-13	Updated functions CalcAllTables/CalcAllTablesPBN.

Rev S, 2014-01-13	Updated functions CalcAllTables/CalcAllTablesPBN.



 

 

