dds-2.4.2+ddd105/0000775000401600040160000000000012267505752011323 5ustar cbecbedds-2.4.2+ddd105/python/0000775000401600040160000000000012267505752012644 5ustar cbecbedds-2.4.2+ddd105/python/pydds.c0000664000401600040160000002451711524510165014131 0ustar cbecbe#include "Python.h" #include "structmember.h" #include "dll.h" #include #include /* type-definition & utility-macros */ typedef struct { PyObject_HEAD int noOfCards; struct dealType deal; } deal_cell; staticforward PyTypeObject deal_type; static char* cardrepr = "AKQJT98765432"; /* static int ones(unsigned int m) { int result = 0; while(m>0) { if(m&1) result++; m>>=1; } return result; } */ static void showdist(unsigned int ca[4][4]) { int h, s; // printf("SD "); for(h=0; h<4; h++) { for(s=0; s<4; s++) { // printf("%d", ones(ca[h][s])); // if(s==3) printf(" "); // else printf("-"); } } // printf("\n"); } static void showdist_short(unsigned short int ca[4][4]) { int h, s; // printf("SDS "); for(h=0; h<4; h++) { for(s=0; s<4; s++) { // printf("%d", ones(ca[h][s])); // if(s==3) printf(" "); // else printf("-"); } } // printf("\n"); } /* ctor (init) and dtor (dealloc) */ static int deal_init(PyObject *self, PyObject *args, PyObject *kwds) { static char* nams[] = {"deal", NULL}; PyObject* indeal; PyObject* seq; int i, j, k; if(!PyArg_ParseTupleAndKeywords(args, kwds, "O", nams, &indeal)) return -1; deal_cell *the_deal = (deal_cell*)self; seq = PySequence_Fast(indeal, "expected deal -> sequence of 4 hands"); if(!seq) return -1; if(PySequence_Fast_GET_SIZE(seq) != 4) { char buf[80]; sprintf(buf, "expected exactly 4 hands, not %d", PySequence_Fast_GET_SIZE(seq)); PyErr_SetString(PyExc_ValueError, buf); Py_DECREF(seq); return -1; } PyObject** hands = PySequence_Fast_ITEMS(seq); PyObject* handseq[4]; Py_DECREF(seq); for(i=0; i<4; i++) { PyObject* h = handseq[i] = PySequence_Fast(hands[i], "each hand must be a sequence of 4 suits"); if(h) { if (PySequence_Fast_GET_SIZE(h) != 4) { char buf[80]; sprintf(buf, "expected exactly 4 suits, not %d, for hand %d", PySequence_Fast_GET_SIZE(h), i); PyErr_SetString(PyExc_ValueError, buf); Py_DECREF(h); handseq[i] = 0; } } if(!handseq[i]) { for(j=0; j=0 && nc != numcards) { char buf[80]; sprintf(buf, "all hands must have same #cards (%d!=%d at %d)", numcards, nc, i); PyErr_SetString(PyExc_ValueError, buf); for(j=0; j<4; j++) Py_DECREF(handseq[j]); return -1; } numcards = nc; } the_deal->noOfCards = numcards; for(i=0; i<4; i++) { PyObject* h = handseq[i]; for(k=0; k<4; k++) { PyObject* suit = PySequence_Fast(PySequence_Fast_GET_ITEM(h, k), "each suit must be SEQ of cards"); for(j=0; jdeal.deal[i][k] |= 1<deal.deal); return 0; } static void deal_dealloc(PyObject *self) { self->ob_type->tp_free(self); } /* methods */ static PyObject* deal_str(PyObject *self) { deal_cell* the_deal = (deal_cell*)self; int i, j, k; char buf[80]; int ib=0; for(i=0; i<4; i++) { for(j=0; j<4; j++) { int mask = 1<<14; for(k=0; k<13; k++) { if (the_deal->deal.deal[i][j] & mask) { buf[ib++] = cardrepr[k]; } mask >>= 1; } if (j<3) buf[ib++] = ' '; } if (i<3) buf[ib++] = '|'; } buf[ib]=0; return PyString_FromFormat("deal c%d %s", the_deal->noOfCards, buf); } static PyObject* deal_solve(PyObject *self, PyObject *args, PyObject *kwds) { static char* nams[] = {"trump", "first", NULL}; int trump=4, first=1; int i, j; if(!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", nams, &trump, &first)) return 0; deal_cell* me = (deal_cell*)self; struct deal d; d.trump = trump; d.first = first; memset(&(d.currentTrickSuit), 0, 3*sizeof(int)); memset(&(d.currentTrickRank), 0, 3*sizeof(int)); for(i=0; i<4; i++) for(j=0; j<4; j++) d.remainCards[i][j] = me->deal.deal[i][j]; showdist(d.remainCards); // printf(" 4"); fflush(0); struct futureTricks futp; int status = SolveBoard(d, -1, 1, 0, &futp); // printf(" 5 %d", status); fflush(0); if (status!=1) { char buf[80]; sprintf(buf, "status: %d", status); PyErr_SetString(PyExc_ValueError, buf); return 0; } PyObject *suit, *rank, *equals, *score; int cards = futp.cards; suit = PyTuple_New(cards); rank = PyTuple_New(cards); equals = PyTuple_New(cards); score = PyTuple_New(cards); for(i=0; i 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. dds-2.4.2+ddd105/release_notes.txt0000664000401600040160000003753112267505310014713 0ustar cbecbeRelease Notes DDS 1.0.1 ----------------------- Includes support for reuse of the transposition table contents for a subsequent search. (This idea was brought forward independently by Alex Martelli and Flip Cronje.) When setting the SolveBoard solutions to 2, the transposition table contents will be reused when searching for alternative cards, giving a slightly decreased search time in most cases, in a few cases the decrease is substantial. Earlier the contents of the transposition table was always emptied between searches. The way to control whether or not to empty the transposition table is to properly set the parameter mtd in the InitSearch function: mtd=FALSE means that the transposition table is emptied, mtd=TRUE that it is not emptied. Release Notes DDS 1.0.2 ----------------------- Includes a bug fix for the case when the SolveBoard parameter "solutions" is set to 3. SolveBoard did not handle correctly the case when the scores of the alternative cards were a mix of zero and non-zero. This is now fixed in 1.0.2. Release Notes DDS 1.0.3 ----------------------- Includes: a) An improvement of the move ordering algorithm. When LHO ruffs, this is now given a low weight if the highest rank of RHO beats both the rank of the leading card and the highest rank of the leading suit at the partner of the leading hand, assuming that the partner of the leading hand is not void in the suit of the leading card. If these conditions do not hold, the weight for the LHO ruffing card is high. b) For the SolveBoard parameter solutions=3, reuse of the transposition table contents between card searches have been added. a) and b) together give on the average an improvement performance. Release Notes DDS 1.0.4 ----------------------- When introducing the possibility of reusing the transposition table between subsequent searches in 1.0.1, unfortunately a bug was introduced as well. It occassionally gives wrong scores when evaluating the last hand of the trick using solutions=2 or 3. This bug is fixed in 1.0.4. Release Notes DDS 1.0.5 -------------------------- 1) About 25% speed improvement due to a search algorithm improvement: For moves generated in the search tree, only one "small" card move per hand and suit is generated. By "small" card is meant a card with a rank that is not winning due to its rank value. Earlier all "small" cards generated their own moves. This improvement comes from a tip by Hans Kuijf. 2) The size of the transposition table has been increased by 25%. This was done after realizing that for some extreme deals, rarely occuring, when solutions=2 and 3 the transposition table could get completely filled up, making the search time extremely long for those cases. The increased transposition table size should still fit well inside a 256 MB machine. 3) Parameter mode=2 indicates that the transposition table is reused from an earlier SolveBoard call. It is restricted to the case where the same conditions apply for the 2 calls, except that the leading hand in the second call is the partner to the leading hand in the first call. I.e. same deal incl same trump suit, same target (not equal to -1), solutions=1. Release Notes DDS 1.0.6 -------------------------- 1) A bug has been fixed in the DDS start up code. The bug did not affect the accuracy of the solver. Thanks to Fabien Bradmetz for spotting this! 2) About 10% increased speed due to improvements in Quick Tricks. 3) An error code has been added for checking the input of of cards earlier played in the trick. 4) A document (mode2.txt) describes source code examples how to call SolveBoard using the parameter mode set to 2. Release Notes DDS 1.1.0 --------------------------- 1) Performance improvement giving a speed of about twice that of 1.0.6. 2) Redesign of the transposition table solution, see algorithm description. 3) Improvements in the Quicktricks algorithm, see algorithm description. 4) Dump in text file of SolveBoard parameters if SolveBoard returns with error code. Release Notes DDS 1.1.1 --------------------------- 1) For target=-1 and solutions=1/2/3, the transposition table contents is now reused also when SolveBoard is called with a new target value. 2) Slight improvement of the QuickTricks algorithm. 3) Moderate speed improvement compared to 1.1.1. Release Notes DDS 1.1.2 --------------------------- 1) Increased performance (about 15%) due to improved algorithm for move ordering. For more information, look in the algorithm description. Release Notes DDS 1.1.3 --------------------------- 1) Compiles with Visual C++ 2005 Express edition 2) Some improvements in move ordering, quick tricks and the new later tricks algorithms. 3) Total improvement about 20% including the faster code generated by Visual C++ and the algorithm improvements. Release Notes DDS 1.1.4 --------------------------- Improvements at usage of the SolveBoard parameter mode set to 2. The mode parameter can now be set to 2 for SolveBoard calls with parameter target set to -1 or a value 0-13, and solutions set to 1, 2 or 3. Following the first SolveBoard call with mode=1, mode can be set to 2 for any further SolveBoard call for the same deal, also when an opponent hand leads the trick. If scores are to be calculated for all 4 possible leading hands of the deal, 1 SolveBoard call can be made with mode=1, and the other 3 SolveBoard calls for the other 3 leading hands can be made with mode=2. Compared to dds 1.1.3, the better support of mode=2 means improved calculation speed. Compared to using only mode=1 at calling Solveboard 4 times, each time for each alternative leading hand, the calculation time is roughly halfed using mode=2 as described above. Release Notes DDS 1.1.5 --------------------------- A correction has been made removing a risk of DD value miscalculation. The fault has not however yet showed up as far as I know. A survival mechanism has been added to handle the situation if the transposition table gets full: The transposition table is emptied. Before this, a full transposition table would in practise lock up the program. Therefore the present size of the transposition table is quite large (393 MB) to handle the most difficult deals. This could lead to extensive memory swapping with the hard drive if the PC RAM size is 256 MB or less, slowing down the program. With the new survival mechanism, the program will not lockup at a full transposition table. The calculation time will increase because of the extra time to build up stored positions in the table, but the increase will be reasonable. This means that DDS should be possible to run with such small PC RAM sizes as 64 MB (this has not been tested though). Release Notes DDS 1.1.6 --------------------------- A bug has been fixed. It could show up (but haven't as far as I know) after the transposition table got full. Only a minor part of the maximum transposition table, about 30 MB, is now allocated at initialization, if more is needed it is dynamically added as need arises. Each incremental addition is about 2 MB. This continues until the maximum allowed space is reached, for 512 MB PC about 400 MB. Then the incrementally added transposition table pieces are wiped out and the initially allocated table is cleared. Release Notes DDS 1.1.7 --------------------------- A bug fix and recoding of the dynamic transposition table implementation. Release Notes DDS 1.1.8 --------------------------- The transposition table solution has been redesigned. Each "winning ranks node" now contains all ranks for one suit. When a new transposition table entry is created, it is now positioned at the front of the alternative "winning ranks node" list rather than at the end as before. Each leading hand has now own root pointers pointing to the "suit lengths combination" tree. Some changes in QuickTricks. Release Notes DDS 1.1.9 ----------------------- Speed increase 10-15% compared to 1.1.8. Main improvements from 1) and 2) below. 1) Much faster initialization of variable rel (struct type relRanksType). Implementation done by Thomas Andrews. 2) Move generation: If the hand-to-play is trick leading hand, the first positions in the move list now come each from a different suit. In 1.1.8, the first positions were groups of 2 cards from each suit. 3) DismissX renamed to NextMove. A bug was corrected in NextMove, increasing performance. (The bug did not give incorrect result.) The bug was found by Jol Bradmetz. 4) The function CountOnes replaced by a table look up. Implementation by Thomas Andrews. 5) The handStore variable replaced by a macro. Based on an implementation by Thomas Andrews. 6) The WinAdapt function replaced by a table look up. 7) A new table highestRank gives the highest rank from a bitmap of ranks. Makes functions UpdateWinner, UpdateSecondBest and QuickTricks slightly faster. Release Notes DDS 2.0.0 ----------------------- A bug was fixed. SolveBoard is now thread-safe. The SolveBoard parameter "mode" no longer needs to be set to 2. DDS automatically detect situations when the transposition table contents can be reused. Used with a single thread, DDS 2.0.0 has about the same speed as DDS 1.1.9. Used with 2 parallel threads, DDS 2.0.0 is twice as fast as the single thread case. A new function, CalcDDtable, has been added. CalcDDtable calls SolveBoard using parallel threads. The number of parallel threads is the same as the number of processor cores. CalcDDtable calculates the double dummy values of the initial 52 cards for all the 20 trump suit/leading hand combinations. Release Notes DDS 2.0.1 ----------------------- In 2.0.0, the contents of the transposition table could be erronously be reused when the previous position contained a different number of cards. This was caused by an erroneous implementation of the deal similarity test. This bug was fixed by removing the similarity test. The DDS version number is defined by a #define statement in dll.h. Release Notes DDS 2.1.0 ----------------------- Added OpenMP as multi-thread support for CalcDDtable when compiling with gcc 4.4.0 or later. Added a similarity deals test function for reuse of the transposition table contents when the current deal is similar to the previous deal. Release Notes DDS 2.1.1 ----------------------- The maximum number of threads is configurable depending on the size of the physical memory. The configuration is either done automatically by reading out the physical memory size by the operating system, or by supplying parameter values in InitStart. Release Notes DDS 2.1.2 ----------------------- 2 new callable functions have been added: SolveBoardPBN and CalcDDtablePBN. They both accept PBN format for the remaining cards in the deal information instead of the bit codes. Code improvements have been done concerning quick tricks detection and move ordering. 2.1.2 is about 10% faster than 2.1.1. Release Notes DDS 1.1.12 ------------------------ 2 new callable functions have been added: SolveBoardPBN and CalcDDtablePBN. They both accept PBN format for the remaining cards in the deal information instead of the bit codes. Code improvements have been done concerning quick tricks detection and move ordering. 1.1.12 is about 15-20% faster than 1.1.11. Release Notes DDS 2.2.0 ----------------------- 1 new callable function has been added: SolveAllBoards. Problems that have been fixed in 2.2.0: 1) DDS used a deficient function in Windows to detect RAM memory size, which could cause too few threads to be allocated. DDS now uses a correct Windows function to detect the RAM size. 2) Failure by DDS to detect PBN text coded card distributions with less than 52 cards. 3) DDS hanged when a faulty card distribution was provided in the CalcDDtable call. This fault was not present in the openMP alternative though. 2.2.0 is 10-15% faster than 2.1.2. Release Notes DDS 1.1.13 ------------------------ Problem that has been fixed in 1.1.13: DDS used a deficient function in Windows to detect RAM memory size, which could cause too few threads to be allocated. DDS now uses a correct Windows function to detect the RAM size. 1.1.13 is 5-10% faster than 1.1.12. Release Notes DDS 2.2.1 ----------------------- Problem fixed in 2.2.1: Fault in using the Windows function to detect RAM memory size that could cause DDS termination. Clarifying that DDS 2.2.1 is a 32-bit DLL not capable of using more than 4 GB. Max threads are 8. Release Notes DDS 1.1.14 ------------------------ Problem fixed in 1.1.14: Fault in using the Windows function to detect RAM memory size that could cause DDS termination. Release Notes DDS 2.2.2 ----------------------- DDS 2.2.2 is mainly a fault correction release. Problems fixed: 1. An uninitialized variable used in move generation required that the compiler initialized it by setting it to zero. This is true for Visual C++ but might perhaps have caused a problem with some other compiler. 2. The rel table missed initialization for absRank and relRank when all cards in a suit are missing. DDS 2.2.2 is slightly faster than 2.2.1, about 4%. Release Notes DDS 1.1.15 ------------------------ Problem fixed in 1.1.15: The rel table missed initialization for absRank and relRank when all cards in a suit are missing. DDS 1.1.15 is about 7% faster than 1.1.14. Release Notes DDS 2.2.3 ----------------------- DDS 2.2.3 add Mingw compiled DLLs and makes a number of code improvements. Maximum number of threads is increased to 16. The 2.2.3 Mingw DLLs are about 5% faster than the 2.2.2 DLLs. Release Notes DDS 1.1.16 ------------------------ DDS 1.1.16 add Mingw compiled DLLs and makes a number of code improvements. The 1.1.16 Mingw DLLs are about 5% faster than the 1.1.15 DLLs. Release Notes DDS 2.2.4 ----------------------- A newer port from GCC to Windows, the TDM-GCC 4.7.1 version is used. It gives faster DLLs and only requires one supporting DLL, which supports OpenMP. Also, the move ordering has been slighly improved. A total speed increase of 4% is achieved compared to 2.2.3. Release Notes DDS 1.1.17 ------------------------ A newer port from GCC to Windows, the TDM-GCC 4.7.1 version is used. It gives faster DLLs and does not require any supporting DLLs. Also, the move ordering has been slighly improved. A total speed increase of 4% is achieved compared to 1.1.16. Release Notes DDS 1.1.18 ------------------------ The main news is that this release is licensed under Apache 2.0 instead of GPL for the previous releases. There is a slight change of the move ordering compared to 1.1.17. Release Notes DDS 2.2.4 ----------------------- A newer port from GCC to Windows, the TDM-GCC 4.7.1 version is used. It gives faster DLLs and only requires one supporting DLL, which supports OpenMP. Also, the move ordering has been slighly improved. A total speed increase of 4% is achieved compared to 2.2.3. Release Notes DDS 2.3.0 ----------------------- The main news is the support of calculation of par scores / contracts. The Mingw DLL now uses the Win API instead of OpenMP so no supporting DLL for pthreads is now needed. Release Notes DDS 2.4.0 ----------------------- Fixing a bug at calculation of par score contracts. Adding the new functions CalcAllTables and CalcAllTablesPBN. Numerous fixes for better adaptation to Linux. Cleaning the code to remove some warnings given at code compilation. For Windows users, adding readable version information of the DDS DLL file. Release Notes DDS 2.4.1 ----------------------- Updates of functions CalcAllTables and CalcAllTablesPBN for improved performance. Release Notes DDS 2.4.2 ----------------------- Fixing bugs in CalcAllTables, CalcAllTablesPBN and CalcPar. dds-2.4.2+ddd105/readme.txt0000664000401600040160000000514712267505310013316 0ustar cbecbeDDS 2.4.2, Bo Haglund 2014-01-09 For Win32, DDS compiles with Visual C++ 2010 and 2012 Express editions and the TDM-GCC/Mingw port of gcc. When using Visual C++, the statement #include "stdafx.h" at the beginning of dds.cpp must be uncommented. Linking with an application using DDS ------------------------------------- The InitStart() function of DDS should be called from inside the application. Then SolveBoard in DDS can be called multiple times without the overhead of InitStart() at each call. For this purpose, the application code must have an include statement for the dll.h file in DDS. Maximum number of threads ------------------------- The maximum number of simultaneous threads depends on the PC physical memory size: 1 GB or less, max 2 threads. 2 GB, max 4 threads. 3 or 4 GB, max 16 threads. For e.g. Windows, allocating memory for the maximum number of simultaneous threads can be done by reading out the physical memory size from Windows. This is done in the DDS.DLL. Another alternative is to provide the physical memory size as a parameter (gb_ram) in the InitStart call. This alternative needs to be used when the operating system does not support memory autoconfiguration. Setting the number of simultaneous threads when calling CalcDDtable. -------------------------------------------------------------------- For Windows, this can be done either by reading out the number of processor cores and using this for setting the number of threads, or by supplying the number of threads (ncores) in InitStart. This latter alternative needs to be used when the operating system does not support reading out of the number of processors. Options at DDS compilation -------------------------- Compiling options: The SolveBoard and CalcDDtable are included in all DDS compilation options. The "PBN" and the "PBN_PLUS" definitions are included in the header fill dll.h. Defining "PBN" means that the functions SolveBoardPBN and CalcDDtablePBN are supported. Defining "PBN_PLUS" as well means that also the SolveAllBoards function, ParCalc and ParCalcPBN are supported. The possible configurens thus are: 1) "PBN" and "PBN_PLUS": Support for SolveBoardPBN, CalcDDtablePBN, SolveAllBoards, SolveAllTables, SolveAllTablesPBN, ParCalc and ParCalcPBN. 2) "PBN": Support for SolveBoardPBN and CalcDDtablePBN. 3) None of these definitions: No support for any of the above 3 functions. Staying with the previous configuration might be needed when 2.4.2 is to replace an older 2.x.y version, and the application using DDS cannot handle a changed interface. dds-2.4.2+ddd105/DLL-dds_242_s.rtf0000664000401600040160000034363212267505310014135 0ustar cbecbe{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff1\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1053\deflangfe1053\themelang1053\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} {\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} {\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} {\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} {\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} {\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} {\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f49\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f50\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;} {\f52\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f53\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f54\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f55\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);} {\f56\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f57\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;} {\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f387\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);} {\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} {\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} {\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} {\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} {\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} {\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} {\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} {\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} {\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} {\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} {\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} {\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} {\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} {\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} {\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} {\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} {\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;} {\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} {\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} {\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} {\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} {\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0; \red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 \snext0 \sqformat \spriority0 Normal;}{\s1\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 \sbasedon0 \snext0 \slink15 \sqformat heading 1;}{ \s2\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 \sbasedon0 \snext0 \slink16 \sqformat heading 2;}{\s3\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 \sbasedon0 \snext0 \slink17 \sqformat heading 3;}{\*\cs10 \additive \sunhideused \spriority1 Default Paragraph Font;}{\* \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1053\langfe1053\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1053\langfenp1053 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \ab\af0\afs32 \ltrch\fcs0 \b\fs32\lang1033\langfe0\kerning32\loch\f31502\hich\af31502\dbch\af31501\langnp1033\langfenp0 \sbasedon10 \slink1 \slocked \spriority9 Rubrik 1 Char;}{\*\cs16 \additive \rtlch\fcs1 \ab\ai\af0\afs28 \ltrch\fcs0 \b\i\fs28\lang1033\langfe0\loch\f31502\hich\af31502\dbch\af31501\langnp1033\langfenp0 \sbasedon10 \slink2 \slocked \ssemihidden \spriority9 Rubrik 2 Char;}{\*\cs17 \additive \rtlch\fcs1 \ab\af0\afs26 \ltrch\fcs0 \b\fs26\lang1033\langfe0\loch\f31502\hich\af31502\dbch\af31501\langnp1033\langfenp0 \sbasedon10 \slink3 \slocked \ssemihidden \spriority9 Rubrik 3 Char;}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid488565\rsid490522\rsid532764 \rsid556337\rsid617158\rsid750573\rsid876335\rsid930020\rsid940090\rsid1187219\rsid1190356\rsid1191142\rsid1258951\rsid1261441\rsid1445386\rsid1706832\rsid1770393\rsid2060511\rsid2112235\rsid2181632\rsid2260548\rsid2443070\rsid2641133\rsid2894529 \rsid3347855\rsid3547548\rsid3819803\rsid4460640\rsid4538894\rsid4542728\rsid4602097\rsid4679726\rsid4981561\rsid5332441\rsid5462095\rsid5525810\rsid5712409\rsid6228168\rsid6309374\rsid6309794\rsid6362316\rsid6569652\rsid6633554\rsid6650094\rsid6845226 \rsid6950962\rsid7041439\rsid7089377\rsid7167315\rsid7421144\rsid7616262\rsid7683346\rsid7807046\rsid7949161\rsid7952569\rsid8001475\rsid8137115\rsid8527940\rsid8541195\rsid8593145\rsid8799536\rsid8983788\rsid8999377\rsid9047914\rsid9125746\rsid9175287 \rsid9314635\rsid9515749\rsid9530285\rsid10426263\rsid10631094\rsid11078728\rsid11279197\rsid11297517\rsid12068517\rsid12087407\rsid12156867\rsid12530193\rsid12595779\rsid12732549\rsid12788235\rsid12854747\rsid12982360\rsid12986669\rsid13174672 \rsid13180120\rsid13316938\rsid13319718\rsid13915886\rsid14095979\rsid14102810\rsid14169293\rsid14295269\rsid14370947\rsid14892228\rsid15031452\rsid15620535\rsid16405367\rsid16470149\rsid16655487}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0 \mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Bo Haglund}{\creatim\yr2012\mo10\dy21\hr14\min22}{\revtim\yr2014\mo1\dy19\hr20\min41}{\version81}{\edmins665}{\nofpages10}{\nofwords3025}{\nofchars16036} {\nofcharsws19023}{\vern49275}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1417\margr1417\margt1417\margb1417\gutter0\ltrsect \widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120 \dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot4538894 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}} {\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}} {\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9 \pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Bo Haglund, Bob Richardson \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid8001475 \hich\af31506\dbch\af31505\loch\f31506 Rev S, 2014-01-18}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 Latest DLL issue with this description is available at }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 HYPERLINK "http://www.bahnhof.se/wb758135/"}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\lang1053\langfe1053\langnp1053\insrsid4538894\charrsid13915886 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5800000068007400740070003a002f002f007700770077002e006200610068006e0068006f0066002e00730065002f00770062003700350038003100330035002f000000795881f43b1d7f48af2c825dc48527630000 0000a5ab00000000004b00000079000000000075000b00006d000000}}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\ul\cf2\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 http://www.bahnhof.se/wb758135/}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \par \par \par }\pard\plain \ltrpar\s2\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\ul\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Short description of the DLL functions supported in D}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\ul\cf1\insrsid11078728 \hich\af31506\dbch\af31505\loch\f31506 ouble Dummy Problem Solver 2.4}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\ul\cf1\insrsid8001475 \hich\af31506\dbch\af31505\loch\f31506 .2}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\ul\cf1\insrsid6650094\charrsid13915886 \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Callable functions \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target, \par \hich\af31506\dbch\af31505\loch\f31506 int solutions, int mode, struct futureTricks *futp, int threadIndex); \par \par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall SolveBoardPBN(struct dealPBN, int target, \par \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 int solutions, int mode, struct futureTricks *futp, int threadIndex); \par \par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall CalcDDtable(struct ddTableDeal tableDeal, \line struct ddTableResults * tablep); \par \par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall CalcDDta\hich\af31506\dbch\af31505\loch\f31506 blePBN(struct ddTableDealPBN\line tableDealPBN, struct ddTableResults * tablep);}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid488565 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid488565 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid488565 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 extern \'93\loch\f31506 \hich\f31506 C\'94\loch\f31506 __declspec(dllimport) int __stdcall }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 CalcAllTables(struct ddTableDeals *dealsp,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565 \line }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565 \hich\af37\dbch\af31505\loch\f37 int mode, int trumpFilter[5], }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 struct ddTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8983788 \hich\af37\dbch\af31505\loch\f37 Res *resp, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6362316 \hich\af37\dbch\af31505\loch\f37 struct allParResults}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 *presp);}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7041439 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 \hich\f37 extern \'93\loch\f37 \hich\f37 C\'94\loch\f37 __declspec(dllimport) int __stdcall CalcAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439 \hich\af37\dbch\af31505\loch\f37 PBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 (struct ddTableDeals}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439 \hich\af37\dbch\af31505\loch\f37 PBN\line *dealsp,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6362316 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 int mode, int trumpFilter[5], struct ddTablesRes *resp, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8983788 \par \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 struct allParResults *presp);}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid488565 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall SolveAll\hich\af31506\dbch\af31505\loch\f31506 Boards(struct boardsPBN *bop, \par \hich\af31506\dbch\af31505\loch\f31506 struct solvedBoards *solvedp); }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669\charrsid13915886 \par \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid12986669 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall CalcPar(struct ddTableDeal tableDeal, int vulnerable, struct ddTableResults * tablep, struct parResults *presp); \par \par \hich\af31506\dbch\af31505\loch\f31506 exter\hich\af31506\dbch\af31505\loch\f31506 n "C" __declspec(dllimport) int __stdcall CalcParPBN(struct ddTableDealPBN tableDealPBN, \par \hich\af31506\dbch\af31505\loch\f31506 struct ddTableR}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2894529 \hich\af31506\dbch\af31505\loch\f31506 esults * tablep, int vulnerable}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 , struct parResults *presp);}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669\charrsid13915886 \par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 SolveBoard \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 SolveBoard is threa}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4542728\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 d-safe, so several threads }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 can call SolveBoa\hich\af31506\dbch\af31505\loch\f31506 rd in parallel.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 The actual}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4542728\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 maximum number is configured at initial start-up, this number is maximum 16. }{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par \par \hich\af31506\dbch\af31505\loch\f31506 Before SolveBoard can be called, a structure of type "futureTricks" must be declared. \par \par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 SolveBoard}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 returns a status integer, "no fault" means the DLL supplies the trick data in the "futureTricks" type structure.\line Status codes: \par \hich\af31506\dbch\af31505\loch\f31506 1=No fault, \par \hich\af31506\dbch\af31505\loch\f31506 -1=Unknown fault, \par \hich\af31506\dbch\af31505\loch\f31506 -2=No of cards = 0, \par \hich\af31506\dbch\af31505\loch\f31506 -3=target > Number of tricks left, \par \hich\af31506\dbch\af31505\loch\f31506 -\hich\af31506\dbch\af31505\loch\f31506 4=Duplicated cards, \par \hich\af31506\dbch\af31505\loch\f31506 -5=target < -1, \par \hich\af31506\dbch\af31505\loch\f31506 -7=target >13, \par \hich\af31506\dbch\af31505\loch\f31506 -8=solutions < 1, \par \hich\af31506\dbch\af31505\loch\f31506 -9=solutions > 3, \par \hich\af31506\dbch\af31505\loch\f31506 -10=No of cards > 52 \par \hich\af31506\dbch\af31505\loch\f31506 -11=Not used \par \hich\af31506\dbch\af31505\loch\f31506 -12=Suit or rank value out of range for deal.currentTrickSuit or deal.currentTrickRank. \par \hich\af31506\dbch\af31505\loch\f31506 -13=Card already played in the cur\hich\af31506\dbch\af31505\loch\f31506 rent trick is also defined as a remaining card to play. \par \hich\af31506\dbch\af31505\loch\f31506 -14=Wrong number of remaining cards for a hand. \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -15=threadIndex < 0 or >=noOfThreads, noOfThreads is the configured maximum number of threads}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 .\line \hich\af31506\dbch\af31505\loch\f31506 \line \hich\f31506 Structure \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 deal}{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 defines all data needed to describe t\hich\af31506\dbch\af31505\loch\f31506 he deal to be analyzed. \par \hich\af31506\dbch\af31505\loch\f31506 struct deal \{}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int trump; /* I.e. which suit that is trump or if contract is NT, Spades=0, Hearts=1, Diamonds=2, Clubs=3, NT=4 */}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int first; /* 0-3, 0=North, 1=East, 2=South, 3=West , Leading hand for the trick.*/}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int currentTrickSuit[3]; /* 0-2 for up to 3 cards in the order played */ \par \hich\af31506\dbch\af31505\loch\f31506 int currentTrickRank[3]; /* 2-14 for up to 3 cards */}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 unsigned int remainCards[4][4]; /* 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index hand (0-3), 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index suit (0-3), values as bitstring of ranks bit 0=0, \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 bit 1=0, bit 2=rank 2, \'85\'85\'85\loch\f31506 . bit 14=rank 14, bit 15=0}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 for cards remaining after already played cards (cards already played to the current trick are not included in this bitstring). \line The decimal value for a card then range between 4 (=rank 2) and 16384 (A\hich\af31506\dbch\af31505\loch\f31506 ce=rank 14). */}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \}\hich\af31506\dbch\af31505\loch\f31506 ;}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par \par \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 is the number of tricks to be won by the side to play, -1 means that the program}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 shall find the maximum number. For equivalent cards only the highest is returned. \par \line \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 solutions}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 defines how many card solut\hich\af31506\dbch\af31505\loch\f31506 ions that SolveBoard must return: \par \hich\af31506\dbch\af31505\loch\f31506 target=1-13, solutions=1: Returns only one of the cards. Its returned score is the same as target when}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8137115 \hich\af31506\dbch\af31505\loch\f31506 }{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target or higher tricks can be won. Otherwise, score \hich\f31506 \endash \loch\f31506 1 is returned if target cannot be reached, or score 0 if no tr\hich\af31506\dbch\af31505\loch\f31506 icks can be won. \line target=-1, solutions=1: Returns only one of the optimum cards and its score. \par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target=0, solutions=1: Returns only one of the cards legal to play with score set to 0.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \line \hich\af31506\dbch\af31505\loch\f31506 target 1-13, solutions=2: Return all cards meeting target. Their\hich\af31506\dbch\af31505\loch\f31506 returned scores are the same as target when target or higher tricks can be won. Otherwise, only one card is returned with score \hich\f31506 \endash \loch\f31506 1 if target cannot be reached, or score 0 for all cards legal to play if no tricks can be won.\line target \hich\f31506 \endash \loch\f31506 1, solutions=2: Ret\hich\af31506\dbch\af31505\loch\f31506 u\hich\af31506\dbch\af31505\loch\f31506 rn all optimum cards with their scores. \par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target=0, solutions=2: Return all cards legal to play with scores set to 0}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf6\insrsid6650094\charrsid13915886 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \line \hich\af31506\dbch\af31505\loch\f31506 target irrelevant, solutions=3: Return all cards that can be legally played w}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8137115 \hich\af31506\dbch\af31505\loch\f31506 ith their scores in descending }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 order. \par \par \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 mode}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 d\hich\af31506\dbch\af31505\loch\f31506 efines the DLL mode of operation.\line mode=0: Do not search to find the score if the hand to play has only one card, including its equivalents, to play. Score is set to \hich\f31506 \endash \loch\f31506 2 for this card, indicating that there are no alternative cards. If there are multiple \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 choices for cards to play, search is done to find the score. This mode is very fast but you don\hich\f31506 \rquote \loch\f31506 t}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8137115 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8137115 \hich\af37\dbch\af31505\loch\f37 a}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8137115\charrsid8137115 \hich\af37\dbch\af31505\loch\f37 lways search to find the score. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \par \hich\af31506\dbch\af31505\loch\f31506 mode=1: Always }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 search to find the score. Even when the hand to play has only one card, \hich\af31506\dbch\af31505\loch\f31506 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. Settin \hich\af31506\dbch\af31505\loch\f31506 g\hich\af31506\dbch\af31505\loch\f31506 mode=2 is no longer needed in this case, but can still be done for backwards compatibility.\line mode=2: As for mode=1, but the transposition table contents is reused from the preceding SolveBoard call. It is the responsibility of the programmer using the \hich\af31506\dbch\af31505\loch\f31506 D\hich\af31506\dbch\af31505\loch\f31506 LL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. \par }\pard \ltrpar\ql \fi720\li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 call: SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1, i.e. East leads. \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \tab 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 call: SolveBoard(deal, -1 \hich\af31506\dbch\af31505\loch\f31506 , 1, 2, &fut, 0), deal.first=2, i.e. South leads. \par \hich\af31506\dbch\af31505\loch\f31506 \tab 3rd call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3, i.e. West leads. \par }\pard \ltrpar\ql \fi720\li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 4th call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0, i.e. North leads. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 struct }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 futureTricks}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \{ /* The DLL prov\hich\af31506\dbch\af31505\loch\f31506 ides the score (number of tricks) that can be won by the card to play defined by its suit and rank. Array of all alternative cards. */}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int nodes; /* Number of searched nodes */ \par \hich\af31506\dbch\af31505\loch\f31506 int cards; /* No of alternative cards */}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int suit[13]; \hich\af31506\dbch\af31505\loch\f31506 /* 0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs */ \par \hich\af31506\dbch\af31505\loch\f31506 int rank[13]; /* 2-14 for 2 through Ace *}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 / \par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int equals[13]; /* Bitstring of ranks for equivalent lower rank cards. The decimal value range between 4 (=2) and 8192 (King=rank 13). When th\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 ere are several \'94\loch\f31506 \hich\f31506 equals \'94\loch\f31506 \hich\f31506 , the value is the sum of each \'94\loch\f31506 \hich\f31506 equal\'94\loch\f31506 . *}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 /}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 int score[13]; /* -1 indicates that target was not reached, otherwise target or max numbe of tricks */}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \}\hich\af31506\dbch\af31505\loch\f31506 ; \par \par \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 threadIndex}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 defines the identity of the t\hich\af31506\dbch\af31505\loch\f31506 hread used when calling SolveBoard. \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16470149\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 A configured maximum number of}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 threads can call SolveBoard in parallel, threadIndex must}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16470149\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 be an integer in the range 0..max number of threads - 1. This maximum number is configured at DLL initial start-up and cannot excee\hich\af31506\dbch\af31505\loch\f31506 d 16.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 SolveBoardPBN \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 In SolveBoardPBN the remaining cards in the deal information are given in PBN text \par \hich\af31506\dbch\af31505\loch\f31506 format (e.g. \line W:T5.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, Solveb\hich\af31506\dbch\af31505\loch\f31506 oardPBN is identical to SolveBoard. \par \par \hich\af31506\dbch\af31505\loch\f31506 struct dealPBN \{ \par \hich\af31506\dbch\af31505\loch\f31506 int trump; \par \hich\af31506\dbch\af31505\loch\f31506 int first; \par \hich\af31506\dbch\af31505\loch\f31506 int currentTrickSuit[3]; }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int currentTrickRank[3]; \par \hich\af31506\dbch\af31505\loch\f31506 char remainCards[80]; /* First character identifies the hand having the cards given first \par \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 in the string, then the cards of the other hands are given in a \par \tab \tab \tab \hich\af31506\dbch\af31505\loch\f31506 clock-wise order, see example above. Null characters fill out \par \tab \tab \tab \hich\af31506\dbch\af31505\loch\f31506 the character array at the end. */ \par \}\hich\af31506\dbch\af31505\loch\f31506 ; \par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \par \par \hich\af31506\dbch\af31505\loch\f31506 CalcDDtable \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par }\pard\plain \ltrpar\s1\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcDDtable }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid1770393 \hich\af31506\dbch\af31505\loch\f31506 calculates the double}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 du\hich\af31506\dbch\af31505\loch\f31506 mmy values of the initial 52 cards for all the 20 trump suit/declarer hand combinations. \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \par }\pard\plain \ltrpar\s1\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Before CalcDDtable can be called, a structure of type " ddTableResults" must be declared. \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcDDtable}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 returns a status integer, "no fault" means the DLL supplies t\hich\af31506\dbch\af31505\loch\f31506 he double dummy scores in the "ddTableResults" type structure.\line Status codes: \par \hich\af31506\dbch\af31505\loch\f31506 1=No fault, \par \hich\af31506\dbch\af31505\loch\f31506 Other status codes are errors, with codes equal to SolveBoard status codes. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Structure \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 ddTableDeal}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 defines the dealt cards to be analyzed.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 struct ddTableDeal \{ \par \hich\af31506\dbch\af31505\loch\f31506 unsigned int cards[4][4]; /* 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index is hand, 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index is suit, same coding as for deal.remainCards for SolveBoard. */ \par \}\hich\af31506\dbch\af31505\loch\f31506 ; \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 struct }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 ddTableResults} {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \{\hich\af31506\dbch\af31505\loch\f31506 /* For each combination trump suit / declarer hand, the DLL provides the double dummy score. */}{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 int resTable[5][4];\tab /* 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No Trump 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index is declarer hand, 0=North, 1=East, 2=South, 3=West *\hich\af31506\dbch\af31505\loch\f31506 / \par \}\hich\af31506\dbch\af31505\loch\f31506 ; \par \par \par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcDDtablePBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \par \par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 In CalcDDtablePBN the remaining cards in the deal information are given in PBN text format, see the description above for SolveBoardPBN. Otherwise, CalcDDtablePBN is identical to CalcDDtable. \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 struct ddTableDealPBN \{ \par \hich\af31506\dbch\af31505\loch\f31506 char cards[80]\hich\af31506\dbch\af31505\loch\f31506 ; \par \}\hich\af31506\dbch\af31505\loch\f31506 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2112235 \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f31506\cf1\insrsid2112235\charrsid7616262 \hich\af31506\dbch\af31505\loch\f31506 CalcAllTables \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 \hich\af37\dbch\af31505\loch\f37 CallAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 \hich\af37\dbch\af31505\loch\f37 calculates }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 the double dummy values }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 \hich\af37\dbch\af31505\loch\f37 of the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 trump suit/declarer hand combinations }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 \hich\af37\dbch\af31505\loch\f37 for }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 a number of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 \hich\af37\dbch\af31505\loch\f37 DD table}{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 s in parallel}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 \hich\af37\dbch\af31505\loch\f37 . This increases}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10631094 \hich\af37\dbch\af31505\loch\f37 the speed}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 compared to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4602097 \hich\af37\dbch\af31505\loch\f37 calculating}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 the}{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 \hich\af37\dbch\af31505\loch\f37 se values}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 using a }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 \hich\af37\dbch\af31505\loch\f37 CalcDDtable call }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 for each }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 \hich\af37\dbch\af31505\loch\f37 DD \hich\af37\dbch\af31505\loch\f37 table}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 \par \hich\af37\dbch\af31505\loch\f37 The maximum number of DD tables in a CallAllTables call depends on the number of strains (the number of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 5 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 \hich\af37\dbch\af31505\loch\f37 trump alternatives, any of the 4 suits and no trump) to be part of the DD calculations. If all 5 strains are included there are 20 declarer ha\hich\af37\dbch\af31505\loch\f37 nd / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14102810 \hich\af37\dbch\af31505\loch\f37 of DD tables that can be included in a CallAllTable call is 10.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 At fewer strains the maximum number of DD tables in a call is higher:}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 4 \hich\af37\dbch\af31505\loch\f37 strains maximum 12 DD tables \par \hich\af37\dbch\af31505\loch\f37 3 strains maximum 16}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 DD tables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \par \hich\af37\dbch\af31505\loch\f37 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 strains maximum }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 25}{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 DD tables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \par \hich\af37\dbch\af31505\loch\f37 1 strain}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 maximum }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 50}{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 DD tables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810\charrsid5525810 \hich\af37\dbch\af31505\loch\f37 Before Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 AllT}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810\charrsid5525810 \hich\af37\dbch\af31505\loch\f37 able}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810\charrsid5525810 \hich\af37\dbch\af31505\loch\f37 can be called, a st}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 ructure of type "ddTable}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15031452 \hich\af37\dbch\af31505\loch\f37 s }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 Res}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810\charrsid5525810 \hich\af37\dbch\af31505\loch\f37 " must be declared.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6569652 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid6569652\charrsid5332441 \hich\af37\dbch\af31505\loch\f37 CallAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652\charrsid6569652 \hich\af37\dbch\af31505\loch\f37 returns a status integer, "no fault" means the DLL supplies the double dum}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15031452 \hich\af37\dbch\af31505\loch\f37 my scores in the "ddTablesRes}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652\charrsid6569652 \hich\af37\dbch\af31505\loch\f37 " type structure.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5332441 \hich\af37\dbch\af31505\loch\f37 \hich\f37 Its contained structure of type \'93\loch\f37 \hich\f37 ddTableResults\'94\loch\f37 is described for the function CalcDDtable.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid617158 \hich\af37\dbch\af31505\loch\f37 \hich\f37 The variable \'93\loch\f37 \hich\f37 noOfBoards\'94\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 show}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid617158 \hich\af37\dbch\af31505\loch\f37 s the number \hich\af37\dbch\af31505\loch\f37 of solved boards (max 200).}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid940090 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090\charrsid940090 \hich\af37\dbch\af31505\loch\f37 struct ddTablesRes \{}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718\charrsid13319718 \hich\af37\dbch\af31505\loch\f37 int noOfBoards;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718\charrsid940090 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090\charrsid940090 \hich\af37\dbch\af31505\loch\f37 struct ddTableResults results[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090\charrsid940090 \hich\af37\dbch\af31505\loch\f37 ]; \par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6569652 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5332441\charrsid6569652 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652\charrsid6569652 \hich\af37\dbch\af31505\loch\f37 Status codes: \par \hich\af37\dbch\af31505\loch\f37 1=No fault,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid8983788 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12156867 \hich\af37\dbch\af31505\loch\f37 -201=Error, all trump suits an}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 d the no trump suit alternative}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12156867 \hich\af37\dbch\af31505\loch\f37 have been marked in the\line ca\hich\af37\dbch\af31505\loch\f37 lling parameter trumpFilter to be left out (i.e. they have }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10631094 \hich\af37\dbch\af31505\loch\f37 all }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2181632 \hich\af37\dbch\af31505\loch\f37 been set to TRUE),}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12087407 \hich\af37\dbch\af31505\loch\f37 -202=Error, too many DD tables in the call. \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6569652 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 \par \hich\af37\dbch\af31505\loch\f37 \hich\f37 Structure \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid940090\charrsid6228168 \hich\af37\dbch\af31505\loch\f37 ddTableDeals}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 \loch\af37\dbch\af31505\hich\f37 \'94\loch\f37 contains }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6228168 \hich\af37\dbch\af31505\loch\f37 up to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6309794 \hich\af37\dbch\af31505\loch\f37 5}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6228168 \hich\af37\dbch\af31505\loch\f37 0 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9125746 \hich\af37\dbch\af31505\loch\f37 DD table }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6228168 \hich\af37\dbch\af31505\loch\f37 \hich\f37 deals, each in a structure \'93\loch\f37 \hich\f37 ddTableDeal\'94\loch\f37 , \par \hich\af37\dbch\af31505\loch\f37 described for the function CalcDDtable.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 The actual number is set in the \loch\af37\dbch\af31505\hich\f37 \'93 \hich\af37\dbch\af31505\loch\f37 noOfTables\loch\af37\dbch\af31505\hich\f37 \'94\hich\af37\dbch\af31505\loch\f37 parameter.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6228168 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6633554 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 struct ddTableDeals \{}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9125746 \hich\af37\dbch\af31505\loch\f37 int noOfTables;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9125746\charrsid6633554 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 struct ddTableDeal deals[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6309794 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 ]; \par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6309794 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid532764 \hich\af37\dbch\af31505\loch\f37 \hich\f37 Parameter \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid532764\charrsid12854747 \hich\af37\dbch\af31505\loch\f37 mode}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid532764 \loch\af37\dbch\af31505\hich\f37 \'94\loch\f37 specifies whether or not par score and par contracts }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10631094 \hich\af37\dbch\af31505\loch\f37 wi}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid532764 \hich\af37\dbch\af31505\loch\f37 ll be calculated\line and if so, wh}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 ich sides that are \hich\af37\dbch\af31505\loch\f37 vulnerable:\line -1}{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid532764 \hich\af37\dbch\af31505\loch\f37 : }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548\charrsid3547548 \hich\af37\dbch\af31505\loch\f37 no par calculation}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid3547548 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548\charrsid3547548 \hich\af37\dbch\af31505\loch\f37 0:\tab par calculation, vulnerability None \par \hich\af37\dbch\af31505\loch\f37 1:\tab par calculation, vulnerability All \par \hich\af37\dbch\af31505\loch\f37 2:\tab par calculation, vulnerability NS}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 only}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548\charrsid3547548 \par \hich\af37\dbch\af31505\loch\f37 3:\tab par calculation, vulnerability EW}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 only \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 \hich\af37\dbch\af31505\loch\f37 The results of the par calculations are giv\hich\af37\dbch\af31505\loch\f37 \hich\f37 en in the structure \'93\loch\f37 \hich\f37 allParResults\'94, \par \hich\af37\dbch\af31505\loch\f37 which contains the results for all boards. Each board results are given\line \hich\f37 in structure \'93\loch\f37 \hich\f37 parResults\'94\loch\f37 , described for the CalcPar function. \par \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6633554 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 struct allParResults \{ \par \hich\af37\dbch\af31505\loch\f37 struct parResults presults[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 ]; \par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 \hich\af37\dbch\af31505\loch\f37 Paramet\hich\af37\dbch\af31505\loch\f37 \hich\f37 er \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid12854747\charrsid7949161 \hich\af37\dbch\af31505\loch\f37 trumpFilter}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 \loch\af37\dbch\af31505\hich\f37 \'94\loch\f37 describes which, if any, of the trump suits or the no trump suit }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7949161 \line \hich\af37\dbch\af31505\loch\f37 alternatives that will be excluded from the calculations.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 They are defined in the order Spades, Hearts, Diamonds, Clubs and No Trump}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid617158 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 . E.g. setting trumpFilter to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12982360 \{\hich\af37\dbch\af31505\loch\f37 FALSE, FAL\hich\af37\dbch\af31505\loch\f37 SE, TRUE, TRUE, TRUE\} means that values will only be calculated for}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12982360 \hich\af37\dbch\af31505\loch\f37 the trump suits Spades and Hearts. \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5712409 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 CalcAllTablesPBN \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12982360 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \hich\af37\dbch\af31505\loch\f37 As for CalcAllTables except that the deals are given in PBN format. The structure\line \hich\f37 \'93\loch\f37 \hich\f37 ddTableDealPBN\'94\loch\f37 is }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 described}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \hich\af37\dbch\af31505\loch\f37 for the CalcDDtablePBN }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14095979 \hich\af37\dbch\af31505\loch\f37 function.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \par \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid2260548 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 struct ddTableDealsPBN \{}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 int noOfTables;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386\charrsid2260548 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 struct ddTableDealPBN deals[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 ]; \par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14095979 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid12982360 \par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 SolveAllBoards}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid7616262\charrsid7616262 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7616262 \hich\af31506\dbch\af31505\loch\f31506 SolveAllBoards solves a}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16405367 \hich\af31506\dbch\af31505\loch\f31506 number of boards in parallel for increased performance compared to solve them sequentionally using a SolveB\hich\af31506\dbch\af31505\loch\f31506 oard call for each board.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7616262 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16405367 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 SolveAllBoards is called with a buffer containi}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7807046 \hich\af31506\dbch\af31505\loch\f31506 ng }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2443070 \hich\af31506\dbch\af31505\loch\f31506 board dat}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7807046 \hich\af31506\dbch\af31505\loch\f31506 a }{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2443070 \hich\af31506\dbch\af31505\loch\f31506 for a }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7807046 \hich\af31506\dbch\af31505\loch\f31506 number of boards, maximum 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 00 boards per call. Each board is defined with the same input data as in SolveBoardPBN. The input data per board can be freely given independent of the settings for the other deals. SolveAllBoards uses multi-thread calls to SolveBoardPBN for solving the b \hich\af31506\dbch\af31505\loch\f31506 u\hich\af31506\dbch\af31505\loch\f31506 ffered boards. \par \par \hich\af31506\dbch\af31505\loch\f31506 struct boardsPBN \{ \par \hich\af31506\dbch\af31505\loch\f31506 int noOfBoards; \par \hich\af31506\dbch\af31505\loch\f31506 struct dealPBN deals[MAXNOOFBOARDS]; \par \hich\af31506\dbch\af31505\loch\f31506 int target[MAXNOOFBOARDS]; \par \hich\af31506\dbch\af31505\loch\f31506 int solutions[MAXNOOFBOARDS]; \par \hich\af31506\dbch\af31505\loch\f31506 int mode[MAXNOOFBOARDS]; \par \}\hich\af31506\dbch\af31505\loch\f31506 ; \par \par \hich\af31506\dbch\af31505\loch\f31506 struct solvedBoards \{ \par \hich\af31506\dbch\af31505\loch\f31506 int noOfBoards; \par \hich\af31506\dbch\af31505\loch\f31506 struct futureTricks solvedBoar\hich\af31506\dbch\af31505\loch\f31506 d[MAXNOOFBOARDS]; \par \}\hich\af31506\dbch\af31505\loch\f31506 ; \par \par \hich\af31506\dbch\af31505\loch\f31506 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}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12595779 \hich\af31506\dbch\af31505\loch\f31506 exceed MAXNOOFBOARDS which is 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 00. In th \hich\af31506\dbch\af31505\loch\f31506 e 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. \par \par \hich\af31506\dbch\af31505\loch\f31506 SolveAllBoards returns 1 if the call suc\hich\af31506\dbch\af31505\loch\f31506 ceeds, otherwise an error code identical to the SolveBoard error codes is given when there is a problem in the input information. \par \par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Note}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid10631094 \hich\af31506\dbch\af31505\loch\f31506 s on DDS use for simulations} {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par \par \hich\af31506\dbch\af31505\loch\f31506 SolveAllBoards is optimal when the input boards are dissimilar. Adjacent boards in the boar\hich\af31506\dbch\af31505\loch\f31506 ds 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. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 In simulation}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid10631094 \hich\af31506\dbch\af31505\loch\f31506 s invo\hich\af31506\dbch\af31505\loch\f31506 lving }{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 different d}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid14169293 \hich\af31506\dbch\af31505\loch\f31506 eclarer hand alternatives and}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1706832 \hich\af31506\dbch\af31505\loch\f31506 possibly also }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 different suit trump alternatives, usage of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7167315 \hich\af31506\dbch\af31505\loch\f31506 Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 AllTables is a more convenient and probably a faster alternative}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 . }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \line \hich\af31506\dbch\af31505\loch\f31506 E.g. if the task is to make simulations to find which of the major suits is best\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2060511 \hich\af31506\dbch\af31505\loch\f31506 in a}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 trump contract and which hand is best as declarer, then }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2060511 \hich\af31506\dbch\af31505\loch\f31506 such}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 simulation is }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2060511 \hich\af31506\dbch\af31505\loch\f31506 easily set up using }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7167315 \hich\af31506\dbch\af31505\loch\f31506 Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2060511 \hich\af31506\dbch\af31505\loch\f31506 AllTables and most likely runs faster than with }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7167315 \hich\af31506\dbch\af31505\loch\f31506 Solve}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2060511 \hich\af31506\dbch\af31505\loch\f31506 AllBoards.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13915886\charrsid13915886 \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f31506\cf1\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcPar \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid556337 \hich\af31506\dbch\af31505\loch\f31506 CalcPar c}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 alculates the par score and par contracts of a given deal.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid750573 \hich\af31506\dbch\af31505\loch\f31506 It also includes calculation and presentation of the double dummy values table otherwise calculated by the CalcDDtable function, since this table is a prerequisite for the par calculations. Thus there is no need to make a CalcDDtable call before calling \hich\af31506\dbch\af31505\loch\f31506 C\hich\af31506\dbch\af31505\loch\f31506 alcPar. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13915886\charrsid13915886 \line \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid13915886 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Before Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid7683346 \hich\af31506\dbch\af31505\loch\f31506 Par}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 \hich\af31506\dbch\af31505\loch\f31506 can be called, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13174672 \hich\af31506\dbch\af31505\loch\f31506 a }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 structure of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13174672 \hich\af31506\dbch\af31505\loch\f31506 each }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 type " ddTableResults" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 and \'93\loch\f31506 \hich\f31506 parResults\'94\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 must be declared. \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 \hich\af31506\dbch\af31505\loch\f31506 CalcPar}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 and the par results in the \'93\loch\f31506 \hich\f31506 parResults\'94\loch\f31506 structure.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid14295269 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Calling CalcPar with the structure of type \'93\loch\f31506 \hich\f31506 ddTableDeal\'94\loch\f31506 is done in the same way as for calling CalcDDtable.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid8527940 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid14295269\charrsid13915886 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Status codes: \par \hich\af31506\dbch\af31505\loch\f31506 1=No fault, \par \hich\af31506\dbch\af31505\loch\f31506 Other status codes are errors, with codes equal to SolveBoa\hich\af31506\dbch\af31505\loch\f31506 rd status codes. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1258951 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f31506\insrsid1261441 \hich\af31506\dbch\af31505\loch\f31506 vulnerable}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 \loch\af31506\dbch\af31505\hich\f31506 \'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid7952569 \hich\af31506\dbch\af31505\loch\f31506 is set according to:}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid7952569 \hich\af31506\dbch\af31505\loch\f31506 0 = None \par \hich\af31506\dbch\af31505\loch\f31506 1 = Both sides \par \hich\af31506\dbch\af31505\loch\f31506 2 = North / South side vulnerable \par \hich\af31506\dbch\af31505\loch\f31506 3 = East / West side vulnerable \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1258951 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid5462095 \hich\af31506\dbch\af31505\loch\f31506 The structure t}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12854747 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 ypes \'93\loch\f31506 \hich\f31506 ddTableDeal\'94\loch\f31506 \hich\f31506 and \'93\loch\f31506 ddTableR}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid5462095 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 esults\'94\loch\f31506 are described for the function CalcDDtable.}{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid5462095 \line \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 The \'93\loch\f31506 \hich\f31506 parResults\'94\loch\f31506 structure type }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid8799536 \hich\af31506\dbch\af31505\loch\f31506 includes the par score and the par contracts results returned by }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 \hich\af31506\dbch\af31505\loch\f31506 the call to CalcPar: \par \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 \hich\af37\dbch\af31505\loch\f37 struct parResults \{ \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid8541195 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 char parScore[2][16];\tab /* index = 0 is from NS view and index =1 is from EW view. */}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 \par \hich\af37\dbch\af31505\loch\f37 char parContractsString[2][12\hich\af37\dbch\af31505\loch\f37 8];}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195\charrsid1190356 \hich\af37\dbch\af31505\loch\f37 /* index = 0 is NS view and index = 1 is EW view. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 \hich\f37 By \'93\loch\f37 \hich\f37 view\'94\loch\f37 is \par }\pard \ltrpar\ql \fi720\li2160\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2160\itap0\pararsid9314635 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 here meant which side that starts the bidding. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195\charrsid1190356 \hich\af37\dbch\af31505\loch\f37 */}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid8799536 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1187219 \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid11297517 \hich\af31506\dbch\af31505\loch\f31506 Par score is give}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 \hich\af31506\dbch\af31505\loch\f31506 n as a text string, e.g NS -460. NS lost 460}{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 points.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 All par contracts }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9515749 \hich\af31506\dbch\af31505\loch\f31506 for different suits }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 are listed with co\hich\af31506\dbch\af31505\loch\f31506 mma separating }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9515749 \hich\af31506\dbch\af31505\loch\f31506 the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 suits.\line Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 \hich\af31506\dbch\af31505\loch\f31506 3, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 4 and 5 in }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13180120 \hich\af31506\dbch\af31505\loch\f31506 No trumps, are}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 \hich\af31506\dbch\af31505\loch\f31506 given as 345N}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 . \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid3347855 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 \hich\af31506\dbch\af31505\loch\f31506 Example of par contracts in different suits: \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726\charrsid4679726 \hich\af37\dbch\af31505\loch\f37 NS:NS 23S,N\hich\af37\dbch\af31505\loch\f37 S 23H}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 This is from the NS view. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726 \hich\af37\dbch\af31505\loch\f37 North}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726 \hich\af37\dbch\af31505\loch\f37 South}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 as declarer make 2 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 or 3 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 \hich\af37\dbch\af31505\loch\f37 Spades and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 Hearts} {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 contracts, 2 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 \hich\af37\dbch\af31505\loch\f37 Spades and 2 H}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 earts with an overtrick.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid9515749 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749\charrsid9515749 \hich\af37\dbch\af31505\loch\f37 If only North could make 3 Hearts, the text string would have looked: \par \hich\af37\dbch\af31505\loch\f37 NS:NS 23S,N 23H}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855\charrsid3347855 \hich\af37\dbch\af31505\loch\f37 NS before the colon refer}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid13180120 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855\charrsid3347855 \hich\af37\dbch\af31505\loch\f37 to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 \hich\af37\dbch\af31505\loch\f37 the}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid12732549 \hich\af37\dbch\af31505\loch\f37 assumed side that made the initial bid in the process for determining the par score / contracts}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 . }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947 \hich\af37\dbch\af31505\loch\f37 Also, DDS calculates the par score / contracts when the assumed side is EW: \par \hich\af37\dbch\af31505\loch\f37 EW}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947\charrsid14370947 \hich\af37\dbch\af31505\loch\f37 :NS 23S,N 23H }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid3347855 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947 \hich\af37\dbch\af31505\loch\f37 Nearly always, the par score / contracts are the same fo \hich\af37\dbch\af31505\loch\f37 r both starting points. One case where they are not is if both sides can make 1 NT but no other contract. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947\charrsid3347855 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid490522 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\insrsid490522\charrsid8593145 \hich\af37\dbch\af31505\loch\f37 CalcParPBN \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid11279197 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 \hich\af37\dbch\af31505\loch\f37 \hich\f37 The only difference compared to CalcPar is that the structure type \'93\loch\f37 \hich\f37 ddTableDealPBN\'94\loch\f37 \hich\f37 is used instead of \'93\loch\f37 \hich\f37 ddTableDeal\'94\loch\f37 . For description o\hich\af37\dbch\af31505\loch\f37 \hich\f37 f \'93\loch\f37 \hich\f37 ddTableDealPBN\'94\loch\f37 , see CalcDDtablePBN.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197\charrsid11279197 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid490522 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid490522\charrsid13915886 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \par }\pard\plain \ltrpar\s1\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Revision History \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par \hich\af31506\dbch\af31505\loch\f31506 Rev A, 2006-02-25.\tab \tab First issue. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev B, 2006-03-20\tab \tab Updated issue. \par \par }\pard \ltrpar\ql \fi-2880\li2880\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2880\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Rev C, 2006-03-28\tab \hich\f31506 Updated issue. Addition of the SolveBoard parameter \'94\loch\f31506 \hich\f31506 mode\'94. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev D, 2006-04-05\tab \hich\af31506\dbch\af31505\loch\f31506 Updated issue. Usage of target=0 to list all cards that are legal to play. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev E, 2006-05-29\tab Updated issue. New error code \hich\f31506 \endash \loch\f31506 10 for number of cards > 52. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev F, 2006-08-09\tab Updated issue. New mode parameter value = 2. New error code \hich\f31506 \endash \hich\af31506\dbch\af31505\loch\f31506 11 for calling SolveBoard with mode = 2 and forbidden values of other parameters. \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \par }\pard \ltrpar\ql \fi-2880\li2880\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2880\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Rev F1, 2006-08-14\tab Clarifications on conditions for returning scores for the different combinations of the values for target and solutions. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev F2, 2006-08-26\tab New error cod\hich\af31506\dbch\af31505\loch\f31506 e \hich\f31506 \endash \loch\f31506 12 for wrongly set valu}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid9047914 \hich\af31506\dbch\af31505\loch\f31506 es of deal.currentTrickSuit and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 deal.currentTrickRank. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev G, 2007-01-04\tab New DDS release 1.1, otherwise no change compared to isse F2. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev H, 2007-04-23\tab DDS release 1.4, changes for parameter mode=2. \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6309374 \hich\af31506\dbch\af31505\loch\f31506 Rev I, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 2010-04-10\tab DDS relea \hich\af31506\dbch\af31505\loch\f31506 se 2.0, multi-thread support. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev J, 2010-05-29\tab DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev K, 2010-10-27\tab Correction of fault in the description: 2nd index in resTable of the structure ddTableR\hich\af31506\dbch\af31505\loch\f31506 esults is declarer hand. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev L, 2011-10-14\tab Added SolveBoardPBN and CalcDDtablePBN. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev M, 2012-07-06\tab Added SolveAllBoards. \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev N, 2012-07-16\tab Max number of threads is 8.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 \par \par \hich\af31506\dbch\af31505\loch\f31506 Rev O, 2012-10-21\tab Max number of threads is }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4542728\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 configured at initial start-up, but nev \hich\af31506\dbch\af31505\loch\f31506 er exceeds 16.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13316938 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938 \hich\af37\dbch\af31505\loch\f37 Rev P, 2013-03-16}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938\charrsid13316938 \tab }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938 \hich\af37\dbch\af31505\loch\f37 Added functions CalcPar and CalcParPBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938\charrsid13316938 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6950962 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9530285 \hich\af37\dbch\af31505\loch\f37 Rev Q, 2014-01-09}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6950962\charrsid6950962 \tab \hich\af37\dbch\af31505\loch\f37 Added functions Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6950962 \hich\af37\dbch\af31505\loch\f37 AllTables/CalcAllTablesPBN. \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 \par \hich\af37\dbch\af31505\loch\f37 Rev R, 2014-01-13\tab Updated }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779\charrsid12595779 \hich\af37\dbch\af31505\loch\f37 functions CalcAllTables/CalcAllTablesPBN.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7089377 \par \hich\af37\dbch\af31505\loch\f37 Rev S}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7089377\charrsid7089377 \hich\af37\dbch\af31505\loch\f37 , 2014-01-13\tab Updated \hich\af37\dbch\af31505\loch\f37 functions CalcAllTables/CalcAllTablesPBN.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7089377 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6950962 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6950962\charrsid13915886 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \par \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f31506\fs20\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \par \par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a 9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad 5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b 4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b 4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210036cc113fa8060000a31b0000160000007468656d652f7468656d652f 7468656d65312e786d6cec594f6f1b4514bf23f11d467b6f6327761a4775aad8b11b48d346b15bd4e37877bc3bcdecce6a669cd437d41e9190100571a012370e 08a8d44a5ccaa709144191fa157833b3bbde89d7246923a8a039b4f6ec6fdefff79b37ebabd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad 79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607f22d771db8b944ad79796a40fcb585ee62949e0d9988b182bf82ac2a540e023901bb3a5e55a6d 7529c634f1508263107b6b3ca63eb9a460abb791cbee31509028a9177c26065a327136186c7050d70839955d26d021666d0fd404fc6848ee2b0f312c153c687b 35f3e72d6d5c5dc2ebd926a616ec2dedeb9bbf6c5fb6213858363a45382a94d6fb8dd695ad42be0130358febf57add5ebd906700d8f7c1536b4b5966a3bf56ef e4324b20fb715e76b7d6ac355c7c49feca9ccdad4ea7d36c65b658a106643f36e6f06bb5d5c6e6b28337208b6fcee11b9dcd6e77d5c11b90c5afcee1fb575aab 0d176f4011a3c9c11c5a27b4dfcfa417903167db95f03580afd532f80c05d55054975631e6895a546b31bec7451f001ac8b0a20952d3948cb10f45dcc5f14850 ac15e075824b4fec922fe796b42e247d4153d5f63e4c3134c44cdeabe7dfbf7afe141d3f7876fce0a7e3870f8f1ffc680539bbb671129677bdfcf6b33f1f7f8c fe78facdcb475f54e36519ffeb0f9ffcf2f3e7d540689f99392fbe7cf2dbb3272fbefaf4f7ef1e55c037051e95e1431a13896e9223b4cf6370cc44c5b59c8cc4 f9760c234ccb3b369350e2046b2d15f27b2a72d037a79865d971ece81037827704d04715f0fae49e63f0201213452b34ef44b103dce59c75b8a88cc28ed6550a f3709284d5cac5a48cdbc7f8b04a7717274e7e7b931478332f4bc7f16e441c33f7184e140e494214d2cff8012115dedda5d489eb2ef505977cacd05d8a3a9856 866448474e35cd366dd318f232adf219f2edc466f70eea7056e5f516397491d0159855183f24cc09e3753c5138ae1239c4312b07fc065651959183a9f0cbb89e 5490e990308e7a0191b26acf2d01fe9692be8381b12ad3becba6b18b148a1e54c9bc81392f23b7f84137c2715a851dd0242a633f900750a218ed715505dfe56e 87e8ef90079c2c4cf71d4a9c749fce06b769e898342b10fd64222a72799d70a77e075336c6c4500d90bac3d5314dfe8eb81905e6b61a2e8eb8812a5f7cfdb8c2 eeb795b237e1f4aaea99ed1344bd0877929ebb5c04f4ed67e72d3c49f60834c4fc11f58e9cdf91b3f79f27e745fd7cf1943c636120683d8bd841db8cddf1c2a9 7b4c191ba8292337a419bc259c3d411f16f53e73e124c52d2c8de0a3ee6450e0e04281cd1e24b8fa88aa6810e11486f6baa7858432131d4a9472099745b35c29 5be361f057f6aad9d49710cb1c12ab5d1ed8e515bd9cdf350a31c6aad05c6873452b5ac05995ad5cc984826fafa3acae8d3ab3b6ba31cd90a2a3ad705987d85c ca21e4856bb0584413861a04a310447915aefc5a355c763023818ebbcd519e1693858b4c918c7040b21c69bfe773543749ca6b65ce11ed872d067d713c256a25 6d2d2df60db49d254965758d05eaf2ecbd4996f20a9e6509a49d6c4796949b9325e8a8edb59acb4d0ff9386d7b63b827c3c73885ac4b3d476216c2bb265f095b f6a736b3e9f259365bb9636e13d4e1d5878dfb9cc30e0fa442aa2d2c235b1ae65156022cd19aacfdcb4d08eb453950c14667b362650d8ae15fb302e2e8a6968c c7c457e564975674ececd78c4af9441131888223346213b18f21fdba54c19f804a78dd6118417f8177733adae6914bce59d395df88199c5dc72c8d7046b7ba45 f34eb6704348850de65bc93cf0add276e3dcf95d312d7f41ae94cbf87fe68a3e4fe0edc34aa033e0c39b618191ee94b6c7858a38b0501a51bf2f607030dc01d5 02ef77e1311415bc9f36ff0b72a8ffb73d676598b6864ba4daa7211214ce23150942f680964cf59d22ac9e9d5d5624cb04998a2a992b536bf6881c1236d41cb8 aacf760f4550ea864d321a30b893f5e77ecf3a6814ea21a7dc6f0e931567afed817f7af2b1cd0c4eb93c6c069a3cfe8589c578303b55ed7eb33d3f7bcb8ee807 b331ab917705282b1d05adaced5fd384731eb596b1e63c5e6ee6c64116e73d86c562204ae11d12d2ffc0f94785cf8829637da00ef93e702b821f2fb430281ba8 ea4b76f0409a20ede2080627bb688b498bb2a1cd46271db5fcb0bee049b7d07b22d8dab2b3e4fb9cc12e8633579dd38b1719ec2cc24eaceddac25043664fb628 2c8df38b8c498cf995acfc4b161fdd83446fc16f0613a6a42926f89d4a6098a107a60fa0f9ad46b375e32f000000ffff0300504b030414000600080000002100 0dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f7 8277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89 d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd500 1996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0f bfff0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6 a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a 0000001c00000000000000000000000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d00140006000800000021 0036cc113fa8060000a31b00001600000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d001400060008 00000021000dd1909fb60000001b0100002700000000000000000000000000b20900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000ad0a00000000} {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} {\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdlocked0 heading 1;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdlocked0 heading 2;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; \lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; \lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; \lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; \lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; \lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; \lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; \lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; \lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; \lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; \lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; \lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; \lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; \lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; \lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; \lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; \lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; \lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; \lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; \lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; \lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; \lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; \lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; \lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; \lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; \lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; \lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; \lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; \lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; \lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; \lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; \lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; \lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; \lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; \lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; \lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; \lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000d026 4d694e15cf01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000105000000000000}}dds-2.4.2+ddd105/dll.h0000664000401600040160000003620012267505310012236 0ustar cbecbe/* portability-macros header prefix */ /* Windows requires a __declspec(dllexport) tag, etc */ #if defined(_WIN32) # define DLLEXPORT __declspec(dllexport) # define STDCALL __stdcall #else # define DLLEXPORT # define STDCALL # define INT8 char #endif #ifdef __cplusplus # define EXTERN_C extern "C" #else # define EXTERN_C #endif #if defined(_WIN32) && defined(__MINGW32__) #define WINVER 0x500 /* Dirty trick, but it works. */ # include # include #endif #if defined(_WIN32) && !defined(__MINGW32__) # include # include #endif #if defined(_MSC_VER) # include #else # include #endif #ifdef __linux__ # include #endif /* end of portability-macros section */ #define DDS_VERSION 20402 /* Version 2.4.2. Allowing for 2 digit minor versions */ #define PBN #define PBN_PLUS /*#define BENCH*/ #include /*#define _CRTDBG_MAP_ALLOC */ /* MEMORY LEAK? */ #include /*#include */ /* MEMORY LEAK? */ #include #include #include #include #ifdef __linux__ typedef long long __int64; #endif /*#define STAT*/ /* Define STAT to generate a statistics log, stat.txt */ /*#define TTDEBUG*/ /* Define TTDEBUG to generate transposition table debug information. Only for a single thread! */ #ifdef TTDEBUG #define SEARCHSIZE 20000 #else #define SEARCHSIZE 1 #endif #if defined(INFINITY) # undef INFINITY #endif #define INFINITY 32000 #define MAXNOOFTHREADS 16 #define MAXNODE 1 #define MINNODE 0 #define TRUE 1 #define FALSE 0 #define MOVESVALID 1 #define MOVESLOCKED 2 #define NSIZE 100000 #define WSIZE 100000 #define LSIZE 20000 #define NINIT 250000 #define WINIT 700000 #define LINIT 50000 #define SIMILARDEALLIMIT 5 #define SIMILARMAXWINNODES 700000 #define MAXNOOFBOARDS 200/*100*/ #define Max(x, y) (((x) >= (y)) ? (x) : (y)) #define Min(x, y) (((x) <= (y)) ? (x) : (y)) /* "hand" is leading hand, "relative" is hand relative leading hand. The handId macro implementation follows a solution by Thomas Andrews. All hand identities are given as 0=NORTH, 1=EAST, 2=SOUTH, 3=WEST. */ #define handId(hand, relative) (hand + relative) & 3 #define CMP_SWAP(i, j) if (a[i].weight < a[j].weight) \ { struct moveType tmp = a[i]; a[i] = a[j]; a[j] = tmp; } struct gameInfo { /* All info of a particular deal */ int declarer; int leadHand; int leadSuit; int leadRank; int first; int noOfCards; unsigned short int suit[4][4]; /* 1st index is hand id, 2nd index is suit id */ }; struct moveType { unsigned char suit; unsigned char rank; unsigned short int sequence; /* Whether or not this move is the first in a sequence */ short int weight; /* Weight used at sorting */ }; struct movePlyType { struct moveType move[14]; int current; int last; }; struct highCardType { int rank; int hand; }; struct futureTricks { int nodes; #ifdef BENCH int totalNodes; #endif int cards; int suit[13]; int rank[13]; int equals[13]; int score[13]; }; struct deal { int trump; int first; int currentTrickSuit[3]; int currentTrickRank[3]; unsigned int remainCards[4][4]; }; struct dealPBN { int trump; int first; int currentTrickSuit[3]; int currentTrickRank[3]; char remainCards[80]; }; struct pos { unsigned short int rankInSuit[4][4]; /* 1st index is hand, 2nd index is suit id */ int orderSet[4]; int winOrderSet[4]; int winMask[4]; int leastWin[4]; unsigned short int removedRanks[4]; /* Ranks removed from board, index is suit */ unsigned short int winRanks[50][4]; /* Cards that win by rank, indices are depth and suit */ unsigned char length[4][4]; char ubound; char lbound; char bestMoveSuit; char bestMoveRank; int first[50]; /* Hand that leads the trick for each ply*/ int high[50]; /* Hand that is presently winning the trick */ struct moveType move[50]; /* Presently winning move */ int handRelFirst; /* The current hand, relative first hand */ int tricksMAX; /* Aggregated tricks won by MAX */ struct highCardType winner[4]; /* Winning rank of the trick, index is suit id. */ struct highCardType secondBest[4]; /* Second best rank, index is suit id. */ }; struct posSearchType { struct winCardType * posSearchPoint; long long suitLengths; struct posSearchType * left; struct posSearchType * right; }; struct nodeCardsType { char ubound; /* ubound and lbound for the N-S side */ char lbound; char bestMoveSuit; char bestMoveRank; char leastWin[4]; }; struct winCardType { int orderSet; int winMask; struct nodeCardsType * first; struct winCardType * prevWin; struct winCardType * nextWin; struct winCardType * next; }; struct evalType { int tricks; unsigned short int winRanks[4]; }; struct absRankType { char rank; char hand; }; struct relRanksType { int aggrRanks[4]; int winMask[4]; char relRank[15][4]; struct absRankType absRank[15][4]; }; struct adaptWinRanksType { unsigned short int winRanks[14]; }; struct ttStoreType { struct nodeCardsType * cardsP; char tricksLeft; char target; char ubound; char lbound; unsigned char first; unsigned short int suit[4][4]; }; struct card { int suit; int rank; }; struct boards { int noOfBoards; struct deal deals[MAXNOOFBOARDS]; int target[MAXNOOFBOARDS]; int solutions[MAXNOOFBOARDS]; int mode[MAXNOOFBOARDS]; }; struct boardsPBN { int noOfBoards; struct dealPBN deals[MAXNOOFBOARDS]; int target[MAXNOOFBOARDS]; int solutions[MAXNOOFBOARDS]; int mode[MAXNOOFBOARDS]; }; struct solvedBoards { int noOfBoards; struct futureTricks solvedBoard[MAXNOOFBOARDS]; }; struct paramType { int noOfBoards; struct boards *bop; struct solvedBoards *solvedp; int error; }; struct ddTableDeal { unsigned int cards[4][4]; }; struct ddTableDeals { int noOfTables; struct ddTableDeal deals[MAXNOOFBOARDS>>2]; }; struct ddTableDealPBN { char cards[80]; }; struct ddTableDealsPBN { int noOfTables; struct ddTableDealPBN deals[MAXNOOFBOARDS>>2]; }; struct ddTableResults { int resTable[5][4]; }; struct ddTablesRes { int noOfBoards; struct ddTableResults results[MAXNOOFBOARDS>>2]; }; struct parResults { char parScore[2][16]; /* index = 0 is NS view and index = 1 is EW view. */ char parContractsString[2][128]; /* index = 0 is NS view and index = 1 is EW view. By view is here meant which side that starts the bidding. */ }; struct allParResults { struct parResults presults[MAXNOOFBOARDS / 20]; }; struct par_suits_type { int suit; int tricks; int score; }; struct localVarType { int nodeTypeStore[4]; int trump; unsigned short int lowestWin[50][4]; int nodes; int trickNodes; int no[50]; int iniDepth; int handToPlay; int payOff; int val; struct pos iniPosition; struct pos lookAheadPos; /* Is initialized for starting alpha-beta search */ struct moveType forbiddenMoves[14]; struct moveType initialMoves[4]; struct moveType cd; struct movePlyType movePly[50]; int tricksTarget; struct gameInfo game; int newDeal; int newTrump; int similarDeal; unsigned short int diffDeal; unsigned short int aggDeal; int estTricks[4]; FILE *fp2; FILE *fp7; FILE *fp11; /*FILE *fdp */ struct moveType bestMove[50]; struct moveType bestMoveTT[50]; struct winCardType temp_win[5]; int nodeSetSizeLimit; int winSetSizeLimit; int lenSetSizeLimit; unsigned long long maxmem; /* bytes */ unsigned long long allocmem; unsigned long long summem; int wmem; int nmem; int lmem; int maxIndex; int wcount; int ncount; int lcount; int clearTTflag; int windex; /*int ttCollect; int suppressTTlog;*/ struct relRanksType * rel; struct adaptWinRanksType * adaptWins; struct posSearchType *rootnp[14][4]; struct winCardType **pw; struct nodeCardsType **pn; struct posSearchType **pl; struct nodeCardsType * nodeCards; struct winCardType * winCards; struct posSearchType * posSearch; /*struct ttStoreType * ttStore; int lastTTstore;*/ unsigned short int iniRemovedRanks[4]; int nodeSetSize; /* Index with range 0 to nodeSetSizeLimit */ int winSetSize; /* Index with range 0 to winSetSizeLimit */ int lenSetSize; /* Index with range 0 to lenSetSizeLimit */ }; extern int noOfThreads; extern int noOfCores; extern struct localVarType localVar[MAXNOOFTHREADS]; extern int * highestRank; extern int * counttable; extern struct adaptWinRanksType * adaptWins; extern unsigned short int bitMapRank[16]; extern unsigned short int relRankInSuit[4][4]; extern int sum; extern int score1Counts[50], score0Counts[50]; extern int c1[50], c2[50], c3[50], c4[50], c5[50], c6[50], c7[50], c8[50], c9[50]; extern int nodeTypeStore[4]; /* Look-up table for determining if node is MAXNODE or MINNODE */ extern int lho[4], rho[4], partner[4]; extern int nodes; /* Number of nodes searched */ extern int no[50]; /* Number of nodes searched on each depth level */ extern int payOff; extern int iniDepth; extern int treeDepth; extern int tricksTarget; /* No of tricks for MAX in order to meet the game goal, e.g. to make the contract */ extern int tricksTargetOpp; /* Target no of tricks for MAX opponent */ extern int targetNS; extern int targetEW; extern int handToPlay; extern int searchTraceFlag; extern int countMax; extern int depthCount; extern int highHand; extern int nodeSetSizeLimit; extern int winSetSizeLimit; extern int lenSetSizeLimit; extern int estTricks[4]; extern int recInd; extern int suppressTTlog; extern unsigned char suitChar[4]; extern unsigned char rankChar[15]; extern unsigned char handChar[4]; extern unsigned char cardRank[15], cardSuit[5], cardHand[4]; extern int totalNodes; extern struct futureTricks fut, ft; extern struct futureTricks *futp; extern char stri[128]; extern FILE *fp, /**fp2, *fp7, *fp11,*/ *fpx; /* Pointers to logs */ extern struct ttStoreType * ttStore; extern int lastTTstore; extern int ttCollect; extern int suppressTTlog; EXTERN_C DLLEXPORT int STDCALL SolveBoard(struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex); EXTERN_C DLLEXPORT int STDCALL CalcDDtable(struct ddTableDeal tableDeal, struct ddTableResults * tablep); #ifdef PBN EXTERN_C DLLEXPORT int STDCALL SolveBoardPBN(struct dealPBN dlpbn, int target, int solutions, int mode, struct futureTricks *futp, int thrId); EXTERN_C DLLEXPORT int STDCALL CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, struct ddTableResults * tablep); #endif #ifdef PBN_PLUS EXTERN_C DLLEXPORT int STDCALL SolveAllBoards(struct boardsPBN *bop, struct solvedBoards *solvedp); EXTERN_C DLLEXPORT int STDCALL CalcAllTables(struct ddTableDeals *dealsp, int mode, int trumpFilter[5], struct ddTablesRes *resp, struct allParResults *presp); EXTERN_C DLLEXPORT int STDCALL CalcAllTablesPBN(struct ddTableDealsPBN *dealsp, int mode, int trumpFilter[5], struct ddTablesRes *resp, struct allParResults *presp); EXTERN_C DLLEXPORT int STDCALL CalcPar(struct ddTableDeal tableDeal, int vulnerable, struct ddTableResults * tablep, struct parResults *presp); EXTERN_C DLLEXPORT int STDCALL CalcParPBN(struct ddTableDealPBN tableDealPBN, struct ddTableResults * tablep, int vulnerable, struct parResults *presp); #endif #ifdef __linux EXTERN_C void InitStart(int gb_ram, int ncores); /* For usage with ctypes in Linux. */ #endif void InitStart(int gb_ram, int ncores); void InitGame(int gameNo, int moveTreeFlag, int first, int handRelFirst, int thrId); void InitSearch(struct pos * posPoint, int depth, struct moveType startMoves[], int first, int mtd, int thrId); int ABsearch(struct pos * posPoint, int target, int depth, int thrId); void Make(struct pos * posPoint, unsigned short int trickCards[4], int depth, int trump, struct movePlyType *mply, int thrId); int MoveGen(struct pos * posPoint, int depth, int trump, struct movePlyType *mply, int thrId); void MergeSort(int n, struct moveType *a); inline int WinningMove(struct moveType * mvp1, struct moveType * mvp2, int trump, int thrId); inline int WinningMoveNT(struct moveType * mvp1, struct moveType * mvp2, int thrId); int AdjustMoveList(int thrId); int QuickTricks(struct pos * posPoint, int hand, int depth, int target, int trump, int *result, int thrId); int LaterTricksMIN(struct pos *posPoint, int hand, int depth, int target, int trump, int thrId); int LaterTricksMAX(struct pos *posPoint, int hand, int depth, int target, int trump, int thrId); struct nodeCardsType * CheckSOP(struct pos * posPoint, struct nodeCardsType * nodep, int target, int tricks, int * result, int *value, int thrId); struct nodeCardsType * UpdateSOP(struct pos * posPoint, struct nodeCardsType * nodep); struct nodeCardsType * FindSOP(struct pos * posPoint, struct winCardType * nodeP, int firstHand, int target, int tricks, int * valp, int thrId); struct nodeCardsType * BuildPath(struct pos * posPoint, struct posSearchType *nodep, int * result, int thrId); void BuildSOP(struct pos * posPoint, int tricks, int firstHand, int target, int depth, int scoreFlag, int score, int thrId); struct posSearchType * SearchLenAndInsert(struct posSearchType * rootp, long long key, int insertNode, int *result, int thrId); void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId); int CheckDeal(struct moveType * cardp, int thrId); int InvBitMapRank(unsigned short bitMap); int InvWinMask(int mask); void ReceiveTTstore(struct pos *posPoint, struct nodeCardsType * cardsP, int target, int depth, int thrId); int NextMove(struct pos *posPoint, int depth, struct movePlyType *mply, int thrId); int DumpInput(int errCode, struct deal dl, int target, int solutions, int mode); void Wipe(int thrId); void AddNodeSet(int thrId); void AddLenSet(int thrId); void AddWinSet(int thrId); void PrintDeal(FILE *fp, unsigned short ranks[4][4]); int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp); int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp); int IsCard(char cardChar); void UpdateDealInfo(int card); int IsVal(char cardChar); dds-2.4.2+ddd105/GPL.txt0000664000401600040160000004310610554446617012513 0ustar cbecbe GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. dds-2.4.2+ddd105/dds.cpp0000664000401600040160000064627512267505310012613 0ustar cbecbe /* DDS 2.4.2 A bridge double dummy solver. */ /* Copyright (C) 2006-2014 by Bo Haglund */ /* Cleanups and porting to Linux and MacOSX (C) 2006 by Alex Martelli. */ /* The code for calculation of par score / contracts is based upon the */ /* perl code written by Matthew Kidd for ACBLmerge. He has kindly given me */ /* permission to include a C++ adaptation in DDS. */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ /* You may obtain a copy of the License at */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /*#include "stdafx.h"*/ /* Needed by Visual C++ */ #include "dll.h" struct localVarType localVar[MAXNOOFTHREADS]; int * counttable; int * highestRank; int lho[4]; int rho[4]; int partner[4]; unsigned short int bitMapRank[16]; unsigned char cardRank[15]; unsigned char cardSuit[5]; unsigned char cardHand[4]; int stat_contr[5]={0,0,0,0,0}; int max_low[3][8]; /* index 1: 0=NT, 1=Major, 2=Minor index 2: contract level 1-7 */ struct ttStoreType * ttStore; int lastTTstore; int ttCollect; int suppressTTlog; int noOfThreads=MAXNOOFTHREADS; /* The number of entries to the transposition tables. There is one entry per thread. */ int noOfCores; /* The number of processor cores, however cannot be higher than noOfThreads. */ #ifdef _MANAGED #pragma managed(push, off) #endif #if defined(_WIN32) extern "C" BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { int k; if (ul_reason_for_call==DLL_PROCESS_ATTACH) { InitStart(0, 0); } else if (ul_reason_for_call==DLL_PROCESS_DETACH) { for (k=0; k=noOfThreads)) { /* Fault corrected after suggestion by Dirk Willecke. */ DumpInput(-15, dl, target, solutions, mode); return -15; } for (k=0; k<=13; k++) { localVar[thrId].forbiddenMoves[k].rank=0; localVar[thrId].forbiddenMoves[k].suit=0; } if (target<-1) { DumpInput(-5, dl, target, solutions, mode); return -5; } if (target>13) { DumpInput(-7, dl, target, solutions, mode); return -7; } if (solutions<1) { DumpInput(-8, dl, target, solutions, mode); return -8; } if (solutions>3) { DumpInput(-9, dl, target, solutions, mode); return -9; } for (k=0; k<=3; k++) noOfCardsPerHand[handId(dl.first, k)]=0; for (k=0; k<=2; k++) { if (dl.currentTrickRank[k]!=0) { noOfCardsPerHand[handId(dl.first, k)]=1; aggrRemain=0; for (h=0; h<=3; h++) aggrRemain|=(dl.remainCards[h][dl.currentTrickSuit[k]]>>2); if ((aggrRemain & bitMapRank[dl.currentTrickRank[k]])!=0) { DumpInput(-13, dl, target, solutions, mode); return -13; } } } if (target==-1) localVar[thrId].tricksTarget=99; else localVar[thrId].tricksTarget=target; localVar[thrId].newDeal=FALSE; localVar[thrId].newTrump=FALSE; localVar[thrId].diffDeal=0; localVar[thrId].aggDeal=0; cardCount=0; for (i=0; i<=3; i++) { for (j=0; j<=3; j++) { cardCount+=counttable[dl.remainCards[i][j]>>2]; localVar[thrId].diffDeal+=((dl.remainCards[i][j]>>2)^ (localVar[thrId].game.suit[i][j])); localVar[thrId].aggDeal+=(dl.remainCards[i][j]>>2); if (localVar[thrId].game.suit[i][j]!=dl.remainCards[i][j]>>2) { localVar[thrId].game.suit[i][j]=dl.remainCards[i][j]>>2; localVar[thrId].newDeal=TRUE; } } } if (localVar[thrId].newDeal) { if (localVar[thrId].diffDeal==0) localVar[thrId].similarDeal=TRUE; else if ((localVar[thrId].aggDeal/localVar[thrId].diffDeal) > SIMILARDEALLIMIT) localVar[thrId].similarDeal=TRUE; else localVar[thrId].similarDeal=FALSE; } else localVar[thrId].similarDeal=FALSE; if (dl.trump!=localVar[thrId].trump) localVar[thrId].newTrump=TRUE; for (i=0; i<=3; i++) for (j=0; j<=3; j++) noOfCardsPerHand[i]+=counttable[localVar[thrId].game.suit[i][j]]; for (i=1; i<=3; i++) { if (noOfCardsPerHand[i]!=noOfCardsPerHand[0]) { DumpInput(-14, dl, target, solutions, mode); return -14; } } if (dl.currentTrickRank[2]) { if ((dl.currentTrickRank[2]<2)||(dl.currentTrickRank[2]>14) ||(dl.currentTrickSuit[2]<0)||(dl.currentTrickSuit[2]>3)) { DumpInput(-12, dl, target, solutions, mode); return -12; } localVar[thrId].handToPlay=handId(dl.first, 3); handRelFirst=3; noStartMoves=3; if (cardCount<=4) { for (k=0; k<=3; k++) { if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { latestTrickSuit[localVar[thrId].handToPlay]=k; latestTrickRank[localVar[thrId].handToPlay]= InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); break; } } latestTrickSuit[handId(dl.first, 2)]=dl.currentTrickSuit[2]; latestTrickRank[handId(dl.first, 2)]=dl.currentTrickRank[2]; latestTrickSuit[handId(dl.first, 1)]=dl.currentTrickSuit[1]; latestTrickRank[handId(dl.first, 1)]=dl.currentTrickRank[1]; latestTrickSuit[dl.first]=dl.currentTrickSuit[0]; latestTrickRank[dl.first]=dl.currentTrickRank[0]; } } else if (dl.currentTrickRank[1]) { if ((dl.currentTrickRank[1]<2)||(dl.currentTrickRank[1]>14) ||(dl.currentTrickSuit[1]<0)||(dl.currentTrickSuit[1]>3)) { DumpInput(-12, dl, target, solutions, mode); return -12; } localVar[thrId].handToPlay=handId(dl.first, 2); handRelFirst=2; noStartMoves=2; if (cardCount<=4) { for (k=0; k<=3; k++) { if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { latestTrickSuit[localVar[thrId].handToPlay]=k; latestTrickRank[localVar[thrId].handToPlay]= InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); break; } } for (k=0; k<=3; k++) { if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) { latestTrickSuit[handId(dl.first, 3)]=k; latestTrickRank[handId(dl.first, 3)]= InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]); break; } } latestTrickSuit[handId(dl.first, 1)]=dl.currentTrickSuit[1]; latestTrickRank[handId(dl.first, 1)]=dl.currentTrickRank[1]; latestTrickSuit[dl.first]=dl.currentTrickSuit[0]; latestTrickRank[dl.first]=dl.currentTrickRank[0]; } } else if (dl.currentTrickRank[0]) { if ((dl.currentTrickRank[0]<2)||(dl.currentTrickRank[0]>14) ||(dl.currentTrickSuit[0]<0)||(dl.currentTrickSuit[0]>3)) { DumpInput(-12, dl, target, solutions, mode); return -12; } localVar[thrId].handToPlay=handId(dl.first,1); handRelFirst=1; noStartMoves=1; if (cardCount<=4) { for (k=0; k<=3; k++) { if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { latestTrickSuit[localVar[thrId].handToPlay]=k; latestTrickRank[localVar[thrId].handToPlay]= InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); break; } } for (k=0; k<=3; k++) { if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) { latestTrickSuit[handId(dl.first, 3)]=k; latestTrickRank[handId(dl.first, 3)]= InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]); break; } } for (k=0; k<=3; k++) { if (localVar[thrId].game.suit[handId(dl.first, 2)][k]!=0) { latestTrickSuit[handId(dl.first, 2)]=k; latestTrickRank[handId(dl.first, 2)]= InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 2)][k]); break; } } latestTrickSuit[dl.first]=dl.currentTrickSuit[0]; latestTrickRank[dl.first]=dl.currentTrickRank[0]; } } else { localVar[thrId].handToPlay=dl.first; handRelFirst=0; noStartMoves=0; if (cardCount<=4) { for (k=0; k<=3; k++) { if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { latestTrickSuit[localVar[thrId].handToPlay]=k; latestTrickRank[localVar[thrId].handToPlay]= InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); break; } } for (k=0; k<=3; k++) { if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) { latestTrickSuit[handId(dl.first, 3)]=k; latestTrickRank[handId(dl.first, 3)]= InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]); break; } } for (k=0; k<=3; k++) { if (localVar[thrId].game.suit[handId(dl.first, 2)][k]!=0) { latestTrickSuit[handId(dl.first, 2)]=k; latestTrickRank[handId(dl.first, 2)]= InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 2)][k]); break; } } for (k=0; k<=3; k++) { if (localVar[thrId].game.suit[handId(dl.first, 1)][k]!=0) { latestTrickSuit[handId(dl.first, 1)]=k; latestTrickRank[handId(dl.first, 1)]= InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 1)][k]); break; } } } } localVar[thrId].trump=dl.trump; localVar[thrId].game.first=dl.first; first=dl.first; localVar[thrId].game.noOfCards=cardCount; if (dl.currentTrickRank[0]!=0) { localVar[thrId].game.leadHand=dl.first; localVar[thrId].game.leadSuit=dl.currentTrickSuit[0]; localVar[thrId].game.leadRank=dl.currentTrickRank[0]; } else { localVar[thrId].game.leadHand=0; localVar[thrId].game.leadSuit=0; localVar[thrId].game.leadRank=0; } for (k=0; k<=2; k++) { localVar[thrId].initialMoves[k].suit=255; localVar[thrId].initialMoves[k].rank=255; } for (k=0; k>2)+2; else totalTricks=((cardCount-4)>>2)+1; checkRes=CheckDeal(&localVar[thrId].cd, thrId); if (localVar[thrId].game.noOfCards<=0) { DumpInput(-2, dl, target, solutions, mode); return -2; } if (localVar[thrId].game.noOfCards>52) { DumpInput(-10, dl, target, solutions, mode); return -10; } if (totalTricksmaxRank)) { maxRank=latestTrickRank[k]; maxSuit=dl.trump; maxHand=k; } } } /* Highest card in leading suit */ if (maxRank==0) { for (k=0; k<=3; k++) { if (k==dl.first) { maxSuit=latestTrickSuit[dl.first]; maxHand=dl.first; maxRank=latestTrickRank[dl.first]; break; } } for (k=0; k<=3; k++) { if ((k!=dl.first)&&(latestTrickSuit[k]==maxSuit)&& (latestTrickRank[k]>maxRank)) { maxHand=k; maxRank=latestTrickRank[k]; } } } futp->nodes=0; #ifdef BENCH futp->totalNodes=0; #endif futp->cards=1; futp->suit[0]=latestTrickSuit[localVar[thrId].handToPlay]; futp->rank[0]=latestTrickRank[localVar[thrId].handToPlay]; futp->equals[0]=0; if ((target==0)&&(solutions<3)) futp->score[0]=0; else if ((localVar[thrId].handToPlay==maxHand)|| (partner[localVar[thrId].handToPlay]==maxHand)) futp->score[0]=1; else futp->score[0]=0; /*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */ return 1; } if ((mode!=2)&& (((localVar[thrId].newDeal)&&(!localVar[thrId].similarDeal)) || localVar[thrId].newTrump || (localVar[thrId].winSetSize > SIMILARMAXWINNODES))) { Wipe(thrId); localVar[thrId].winSetSizeLimit=WINIT; localVar[thrId].nodeSetSizeLimit=NINIT; localVar[thrId].lenSetSizeLimit=LINIT; localVar[thrId].allocmem=(WINIT+1)*sizeof(struct winCardType); localVar[thrId].allocmem+=(NINIT+1)*sizeof(struct nodeCardsType); localVar[thrId].allocmem+=(LINIT+1)*sizeof(struct posSearchType); localVar[thrId].winCards=localVar[thrId].pw[0]; localVar[thrId].nodeCards=localVar[thrId].pn[0]; localVar[thrId].posSearch=localVar[thrId].pl[0]; localVar[thrId].wcount=0; localVar[thrId].ncount=0; localVar[thrId].lcount=0; InitGame(0, FALSE, first, handRelFirst, thrId); } else { InitGame(0, TRUE, first, handRelFirst, thrId); /*localVar[thrId].fp2=fopen("dyn.txt", "a"); fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n", wcount, ncount, lcount); fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n", winSetSize, nodeSetSize, lenSetSize); fclose(localVar[thrId].fp2);*/ } localVar[thrId].nodes=0; localVar[thrId].trickNodes=0; localVar[thrId].iniDepth=cardCount-4; hiwinSetSize=0; hinodeSetSize=0; if (mode==0) { MoveGen(&localVar[thrId].lookAheadPos, localVar[thrId].iniDepth, localVar[thrId].trump, &localVar[thrId].movePly[localVar[thrId].iniDepth], thrId); if (localVar[thrId].movePly[localVar[thrId].iniDepth].last==0) { futp->nodes=0; #ifdef BENCH futp->totalNodes=0; #endif futp->cards=1; futp->suit[0]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].suit; futp->rank[0]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].rank; futp->equals[0]= localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].sequence<<2; futp->score[0]=-2; /*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */ return 1; } } if ((target==0)&&(solutions<3)) { MoveGen(&localVar[thrId].lookAheadPos, localVar[thrId].iniDepth, localVar[thrId].trump, &localVar[thrId].movePly[localVar[thrId].iniDepth], thrId); futp->nodes=0; #ifdef BENCH futp->totalNodes=0; #endif for (k=0; k<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; k++) { futp->suit[k]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].suit; futp->rank[k]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].rank; futp->equals[k]= localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].sequence<<2; futp->score[k]=0; } if (solutions==1) futp->cards=1; else futp->cards=localVar[thrId].movePly[localVar[thrId].iniDepth].last+1; /*_CrtDumpMemoryLeaks(); */ /* MEMORY LEAK? */ return 1; } if ((target!=-1)&&(solutions!=3)) { localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, localVar[thrId].tricksTarget, localVar[thrId].iniDepth, thrId); temp=localVar[thrId].movePly[localVar[thrId].iniDepth]; last=localVar[thrId].movePly[localVar[thrId].iniDepth].last; noMoves=last+1; hiwinSetSize=localVar[thrId].winSetSize; hinodeSetSize=localVar[thrId].nodeSetSize; hilenSetSize=localVar[thrId].lenSetSize; if (localVar[thrId].nodeSetSize>MaxnodeSetSize) MaxnodeSetSize=localVar[thrId].nodeSetSize; if (localVar[thrId].winSetSize>MaxwinSetSize) MaxwinSetSize=localVar[thrId].winSetSize; if (localVar[thrId].lenSetSize>MaxlenSetSize) MaxlenSetSize=localVar[thrId].lenSetSize; if (localVar[thrId].val==1) localVar[thrId].payOff=localVar[thrId].tricksTarget; else localVar[thrId].payOff=0; futp->cards=1; ind=2; if (localVar[thrId].payOff<=0) { futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit; futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank; futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2; if (localVar[thrId].tricksTarget>1) futp->score[0]=-1; else futp->score[0]=0; } else { futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; futp->rank[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; futp->score[0]=localVar[thrId].payOff; } } else { g=localVar[thrId].estTricks[localVar[thrId].handToPlay]; upperbound=13; lowerbound=0; do { if (g==lowerbound) tricks=g+1; else tricks=g; assert((localVar[thrId].lookAheadPos.handRelFirst>=0)&& (localVar[thrId].lookAheadPos.handRelFirst<=3)); localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, tricks, localVar[thrId].iniDepth, thrId); if (localVar[thrId].val==TRUE) mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]; hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize); hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize); hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize); if (localVar[thrId].nodeSetSize>MaxnodeSetSize) MaxnodeSetSize=localVar[thrId].nodeSetSize; if (localVar[thrId].winSetSize>MaxwinSetSize) MaxwinSetSize=localVar[thrId].winSetSize; if (localVar[thrId].lenSetSize>MaxlenSetSize) MaxlenSetSize=localVar[thrId].lenSetSize; if (localVar[thrId].val==FALSE) { upperbound=tricks-1; g=upperbound; } else { lowerbound=tricks; g=lowerbound; } InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, localVar[thrId].initialMoves, first, TRUE, thrId); } while (lowerboundcards=1; if (localVar[thrId].payOff<=0) { futp->score[0]=0; futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit; futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank; futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2; } else { futp->score[0]=localVar[thrId].payOff; futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; futp->rank[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; } localVar[thrId].tricksTarget=localVar[thrId].payOff; } if ((solutions==2)&&(localVar[thrId].payOff>0)) { forb=1; ind=forb; while ((localVar[thrId].payOff==localVar[thrId].tricksTarget)&&(ind<(temp.last+1))) { localVar[thrId].forbiddenMoves[forb].suit=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; localVar[thrId].forbiddenMoves[forb].rank=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; forb++; ind++; /* All moves before bestMove in the move list shall be moved to the forbidden moves list, since none of them reached the target */ /*mcurr=localVar[thrId].movePly[localVar[thrId].iniDepth].current;*/ for (k=0; k<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; k++) if ((localVar[thrId].bestMove[localVar[thrId].iniDepth].suit== localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].suit) &&(localVar[thrId].bestMove[localVar[thrId].iniDepth].rank== localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].rank)) break; for (i=0; iMaxnodeSetSize) MaxnodeSetSize=localVar[thrId].nodeSetSize; if (localVar[thrId].winSetSize>MaxwinSetSize) MaxwinSetSize=localVar[thrId].winSetSize; if (localVar[thrId].lenSetSize>MaxlenSetSize) MaxlenSetSize=localVar[thrId].lenSetSize; if (localVar[thrId].val==TRUE) { localVar[thrId].payOff=localVar[thrId].tricksTarget; futp->cards=ind; futp->suit[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; futp->rank[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; futp->score[ind-1]=localVar[thrId].payOff; } else localVar[thrId].payOff=0; } } else if ((solutions==2)&&(localVar[thrId].payOff==0)&& ((target==-1)||(localVar[thrId].tricksTarget==1))) { futp->cards=noMoves; /* Find the cards that were in the initial move list but have not been listed in the current result */ n=0; for (i=0; isuit[0])&& (temp.move[i].rank==futp->rank[0])) { found=TRUE; } if (!found) { futp->suit[1+n]=temp.move[i].suit; futp->rank[1+n]=temp.move[i].rank; futp->equals[1+n]=(temp.move[i].sequence)<<2; futp->score[1+n]=0; n++; } } } if ((solutions==3)&&(localVar[thrId].payOff>0)) { forb=1; ind=forb; for (i=0; i=0)&& (localVar[thrId].lookAheadPos.handRelFirst<=3)); localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, tricks, localVar[thrId].iniDepth, thrId); if (localVar[thrId].val==TRUE) mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]; hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize); hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize); hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize); if (localVar[thrId].nodeSetSize>MaxnodeSetSize) MaxnodeSetSize=localVar[thrId].nodeSetSize; if (localVar[thrId].winSetSize>MaxwinSetSize) MaxwinSetSize=localVar[thrId].winSetSize; if (localVar[thrId].lenSetSize>MaxlenSetSize) MaxlenSetSize=localVar[thrId].lenSetSize; if (localVar[thrId].val==FALSE) { upperbound=tricks-1; g=upperbound; } else { lowerbound=tricks; g=lowerbound; } InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, localVar[thrId].initialMoves, first, TRUE, thrId); } while (lowerboundcards=temp.last+1; for (j=0; j<=last; j++) { futp->suit[ind-1+j]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].suit; futp->rank[ind-1+j]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].rank; futp->equals[ind-1+j]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].sequence)<<2; futp->score[ind-1+j]=localVar[thrId].payOff; } break; } else { localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]=mv; futp->cards=ind; futp->suit[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; futp->rank[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; futp->score[ind-1]=localVar[thrId].payOff; } } } else if ((solutions==3)&&(localVar[thrId].payOff==0)) { futp->cards=noMoves; /* Find the cards that were in the initial move list but have not been listed in the current result */ n=0; for (i=0; isuit[0])&& (temp.move[i].rank==futp->rank[0])) { found=TRUE; } if (!found) { futp->suit[1+n]=temp.move[i].suit; futp->rank[1+n]=temp.move[i].rank; futp->equals[1+n]=(temp.move[i].sequence)<<2; futp->score[1+n]=0; n++; } } } for (k=0; k<=13; k++) { localVar[thrId].forbiddenMoves[k].suit=0; localVar[thrId].forbiddenMoves[k].rank=0; } futp->nodes=localVar[thrId].trickNodes; #ifdef BENCH futp->totalNodes=localVar[thrId].nodes; #endif /*if ((wcount>0)||(ncount>0)||(lcount>0)) { localVar[thrId].fp2=fopen("dyn.txt", "a"); fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n", wcount, ncount, lcount); fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n", winSetSize, nodeSetSize, lenSetSize); fprintf(localVar[thrId].fp2, "\n"); fclose(localVar[thrId].fp2); }*/ /*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */ return 1; } int _initialized=0; void InitStart(int gb_ram, int ncores) { int k, r, i, j, m; unsigned short int res; unsigned long long pcmem; /* kbytes */ if (_initialized) return; _initialized = 1; ttCollect=FALSE; suppressTTlog=FALSE; lastTTstore=0; ttStore = (struct ttStoreType *)calloc(SEARCHSIZE, sizeof(struct ttStoreType)); if (ttStore==NULL) exit(1); if (gb_ram==0) { /* Autoconfig */ #ifdef _WIN32 SYSTEM_INFO temp; MEMORYSTATUSEX statex; statex.dwLength = sizeof (statex); GlobalMemoryStatusEx (&statex); /* Using GlobalMemoryStatusEx instead of GlobalMemoryStatus was suggested by Lorne Anderson. */ pcmem=(unsigned long long)statex.ullTotalPhys/1024; if (pcmem < 1500000) noOfThreads=Min(MAXNOOFTHREADS, 2); else if (pcmem < 2500000) noOfThreads=Min(MAXNOOFTHREADS, 4); else noOfThreads=MAXNOOFTHREADS; GetSystemInfo(&temp); noOfCores=Min(noOfThreads, (int)temp.dwNumberOfProcessors); #endif #ifdef __linux__ /* The code for linux was suggested by Antony Lee. */ ncores = sysconf(_SC_NPROCESSORS_ONLN); FILE* fifo = popen("free -k | tail -n+3 | head -n1 | awk '{print $NF}'", "r"); fscanf(fifo, "%lld", &pcmem); fclose(fifo); #endif } else { if (gb_ram < 2) noOfThreads=Min(MAXNOOFTHREADS, 2); else if (gb_ram < 3) noOfThreads=Min(MAXNOOFTHREADS, 4); else noOfThreads=Min(MAXNOOFTHREADS, 8); noOfCores=Min(noOfThreads, ncores); pcmem=(unsigned long long)(1000000 * gb_ram); } /*printf("noOfThreads: %d noOfCores: %d\n", noOfThreads, noOfCores);*/ for (k=0; k=2; r--) { if ((k & bitMapRank[r])!=0) { highestRank[k]=r; break; } } } /* The use of the counttable to give the number of bits set to one in an integer follows an implementation by Thomas Andrews. */ counttable = (int *)calloc(8192, sizeof(int)); if (counttable==NULL) exit(1); for (i=0; i<8192; i++) { counttable[i]=0; for (j=0; j<13; j++) { if (i & (1<=2; r--) { if ((i & bitMapRank[r])!=0) { if (k <= j) { res|=bitMapRank[r]; k++; } else break; } } for (m=0; m=(topBitRank+topBitRank)) { /* Next top bit */ topBitRank <<=1; } localVar[thrId].rel[ind]=localVar[thrId].rel[ind ^ topBitRank]; for (s=0; s<4; s++) { ord=0; for (r=14; r>=2; r--) { if ((ind & bitMapRank[r])!=0) { ord++; localVar[thrId].rel[ind].relRank[r][s]=ord; for (h=0; h<4; h++) { if ((localVar[thrId].game.suit[h][s] & bitMapRank[r])!=0) { localVar[thrId].rel[ind].absRank[ord][s].hand=h; localVar[thrId].rel[ind].absRank[ord][s].rank=r; break; } } } } for (k=ord+1; k<=13; k++) { localVar[thrId].rel[ind].absRank[k][s].hand=-1; localVar[thrId].rel[ind].absRank[k][s].rank=0; } for (h=0; h<4; h++) { if (localVar[thrId].game.suit[h][s] & topBitRank) { localVar[thrId].rel[ind].aggrRanks[s]= (localVar[thrId].rel[ind].aggrRanks[s]>>2)|(h<<24); localVar[thrId].rel[ind].winMask[s]= (localVar[thrId].rel[ind].winMask[s]>>2)|(3<<24); break; } } } } } localVar[thrId].iniPosition.first[localVar[thrId].game.noOfCards-4]=first; localVar[thrId].iniPosition.handRelFirst=handRelFirst; localVar[thrId].lookAheadPos=localVar[thrId].iniPosition; localVar[thrId].estTricks[1]=6; localVar[thrId].estTricks[3]=6; localVar[thrId].estTricks[0]=7; localVar[thrId].estTricks[2]=7; #ifdef STAT fprintf(localVar[thrId].fp2, "Estimated tricks for hand to play:\n"); fprintf(localVar[thrId].fp2, "hand=%d est tricks=%d\n", localVar[thrId].handToPlay, localVar[thrId].estTricks[localVar[thrId].handToPlay]); #endif InitSearch(&localVar[thrId].lookAheadPos, localVar[thrId].game.noOfCards-4, localVar[thrId].initialMoves, first, moveTreeFlag, thrId); return; } void InitSearch(struct pos * posPoint, int depth, struct moveType startMoves[], int first, int mtd, int thrId) { int s, d, h, handRelFirst, maxAgg, maxHand=0; int k, noOfStartMoves; /* Number of start moves in the 1st trick */ int hand[3], suit[3], rank[3]; struct moveType move; unsigned short int startMovesBitMap[4][4]; /* Indices are hand and suit */ unsigned short int aggHand[4][4]; for (h=0; h<=3; h++) for (s=0; s<=3; s++) startMovesBitMap[h][s]=0; handRelFirst=posPoint->handRelFirst; noOfStartMoves=handRelFirst; for (k=0; k<=2; k++) { hand[k]=handId(first, k); suit[k]=startMoves[k].suit; rank[k]=startMoves[k].rank; if (kfirst[depth]=first; posPoint->handRelFirst=k; assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); posPoint->tricksMAX=0; if (k>0) { posPoint->move[depth+k]=startMoves[k-1]; move=startMoves[k-1]; } posPoint->high[depth+k]=first; while (k>0) { localVar[thrId].movePly[depth+k].current=0; localVar[thrId].movePly[depth+k].last=0; localVar[thrId].movePly[depth+k].move[0].suit=startMoves[k-1].suit; localVar[thrId].movePly[depth+k].move[0].rank=startMoves[k-1].rank; if (kmove[depth+k].suit=startMoves[k-1].suit; posPoint->move[depth+k].rank=startMoves[k-1].rank; posPoint->high[depth+k]=handId(first, noOfStartMoves-k); move=posPoint->move[depth+k]; } else { posPoint->move[depth+k]=posPoint->move[depth+k+1]; posPoint->high[depth+k]=posPoint->high[depth+k+1]; } } k--; } for (s=0; s<=3; s++) posPoint->removedRanks[s]=0; for (s=0; s<=3; s++) /* Suit */ for (h=0; h<=3; h++) /* Hand */ posPoint->removedRanks[s]|= posPoint->rankInSuit[h][s]; for (s=0; s<=3; s++) posPoint->removedRanks[s]=~(posPoint->removedRanks[s]); for (s=0; s<=3; s++) /* Suit */ for (h=0; h<=3; h++) /* Hand */ posPoint->removedRanks[s]&= (~startMovesBitMap[h][s]); for (s=0; s<=3; s++) localVar[thrId].iniRemovedRanks[s]=posPoint->removedRanks[s]; /*for (d=0; d<=49; d++) { for (s=0; s<=3; s++) posPoint->winRanks[d][s]=0; }*/ /* Initialize winning and second best ranks */ for (s=0; s<=3; s++) { maxAgg=0; for (h=0; h<=3; h++) { aggHand[h][s]=startMovesBitMap[h][s] | localVar[thrId].game.suit[h][s]; if (aggHand[h][s]>maxAgg) { maxAgg=aggHand[h][s]; maxHand=h; } } if (maxAgg!=0) { posPoint->winner[s].hand=maxHand; k=highestRank[aggHand[maxHand][s]]; posPoint->winner[s].rank=k; maxAgg=0; for (h=0; h<=3; h++) { aggHand[h][s]&=(~bitMapRank[k]); if (aggHand[h][s]>maxAgg) { maxAgg=aggHand[h][s]; maxHand=h; } } if (maxAgg>0) { posPoint->secondBest[s].hand=maxHand; posPoint->secondBest[s].rank=highestRank[aggHand[maxHand][s]]; } else { posPoint->secondBest[s].hand=-1; posPoint->secondBest[s].rank=0; } } else { posPoint->winner[s].hand=-1; posPoint->winner[s].rank=0; posPoint->secondBest[s].hand=-1; posPoint->secondBest[s].rank=0; } } for (s=0; s<=3; s++) for (h=0; h<=3; h++) posPoint->length[h][s]= (unsigned char)counttable[posPoint->rankInSuit[h][s]]; #ifdef STAT for (d=0; d<=49; d++) { score1Counts[d]=0; score0Counts[d]=0; c1[d]=0; c2[d]=0; c3[d]=0; c4[d]=0; c5[d]=0; c6[d]=0; c7[d]=0; c8[d]=0; localVar[thrId].no[d]=0; } #endif if (!mtd) { localVar[thrId].lenSetSize=0; for (k=0; k<=13; k++) { for (h=0; h<=3; h++) { localVar[thrId].rootnp[k][h]=&localVar[thrId].posSearch[localVar[thrId].lenSetSize]; localVar[thrId].posSearch[localVar[thrId].lenSetSize].suitLengths=0; localVar[thrId].posSearch[localVar[thrId].lenSetSize].posSearchPoint=NULL; localVar[thrId].posSearch[localVar[thrId].lenSetSize].left=NULL; localVar[thrId].posSearch[localVar[thrId].lenSetSize].right=NULL; localVar[thrId].lenSetSize++; } } localVar[thrId].nodeSetSize=0; localVar[thrId].winSetSize=0; } #ifdef TTDEBUG if (!suppressTTlog) lastTTstore=0; #endif return; } #ifdef STAT int score1Counts[50], score0Counts[50]; int sumScore1Counts, sumScore0Counts, dd, suit, rank, order; int c1[50], c2[50], c3[50], c4[50], c5[50], c6[50], c7[50], c8[50], c9[50]; int sumc1, sumc2, sumc3, sumc4, sumc5, sumc6, sumc7, sumc8, sumc9; #endif int ABsearch(struct pos * posPoint, int target, int depth, int thrId) { /* posPoint points to the current look-ahead position, target is number of tricks to take for the player, depth is the remaining search length, must be positive, the value of the subtree is returned. */ int moveExists, mexists, value, hand, scoreFlag, found, trump; int ready, hfirst, hh, ss, rr, mcurrent, qtricks, tricks, res, k; unsigned short int makeWinRank[4]; struct nodeCardsType * cardsP; struct evalType evalData; struct winCardType * np; struct posSearchType * pp; struct nodeCardsType * tempP; struct movePlyType *mply; unsigned short int aggr[4]; unsigned short int ranks; long long suitLengths; struct evalType Evaluate(struct pos * posPoint, int trump, int thrId); void Make(struct pos * posPoint, unsigned short int trickCards[4], int depth, int trump, struct movePlyType *mply, int thrId); void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId); /*cardsP=NULL;*/ assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); trump=localVar[thrId].trump; hand=handId(posPoint->first[depth], posPoint->handRelFirst); localVar[thrId].nodes++; if (posPoint->handRelFirst==0) { localVar[thrId].trickNodes++; if (posPoint->tricksMAX>=target) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; #ifdef STAT c1[depth]++; score1Counts[depth]++; if (depth==localVar[thrId].iniDepth) { fprintf(localVar[thrId].fp2, "score statistics:\n"); for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], c4[dd]); fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd], c7[dd], c8[dd]); } } #endif return TRUE; } if (((posPoint->tricksMAX+(depth>>2)+1)0)*/) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; #ifdef STAT c2[depth]++; score0Counts[depth]++; if (depth==localVar[thrId].iniDepth) { fprintf(localVar[thrId].fp2, "score statistics:\n"); for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], c4[dd]); fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd], c7[dd], c8[dd]); } } #endif return FALSE; } if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { qtricks=QuickTricks(posPoint, hand, depth, target, trump, &res, thrId); if (res) { if (qtricks==0) return FALSE; else return TRUE; #ifdef STAT c3[depth]++; score1Counts[depth]++; if (depth==localVar[thrId].iniDepth) { fprintf(localVar[thrId].fp2, "score statistics:\n"); for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], c4[dd]); fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd], c7[dd], c8[dd]); } } #endif } if (!LaterTricksMIN(posPoint,hand,depth,target,trump,thrId)) return FALSE; } else { qtricks=QuickTricks(posPoint, hand, depth, target, trump, &res, thrId); if (res) { if (qtricks==0) return TRUE; else return FALSE; #ifdef STAT c4[depth]++; score0Counts[depth]++; if (depth==localVar[thrId].iniDepth) { fprintf(localVar[thrId].fp2, "score statistics:\n"); for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], c4[dd]); fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd], c7[dd], c8[dd]); } } #endif } if (LaterTricksMAX(posPoint,hand,depth,target,trump,thrId)) return TRUE; } } else if (posPoint->handRelFirst==1) { ss=posPoint->move[depth+1].suit; ranks=posPoint->rankInSuit[hand][ss] | posPoint->rankInSuit[partner[hand]][ss]; found=FALSE; rr=0; qtricks=0; if ((trump!=4) && (ss!=trump) && (((posPoint->rankInSuit[hand][ss]==0) && (posPoint->rankInSuit[hand][trump]!=0))|| ((posPoint->rankInSuit[partner[hand]][ss]==0) && (posPoint->rankInSuit[partner[hand]][trump]!=0)))) { /* Own side can ruff */ if ((posPoint->rankInSuit[lho[hand]][ss]!=0)|| (posPoint->rankInSuit[lho[hand]][trump]==0)) { found=TRUE; qtricks=1; } } else if ( ranks >(bitMapRank[posPoint->move[depth+1].rank] | posPoint->rankInSuit[lho[hand]][ss])) { /* Own side has highest card in suit */ if ((trump==4) || ((ss==trump)|| (posPoint->rankInSuit[lho[hand]][trump]==0) || (posPoint->rankInSuit[lho[hand]][ss]!=0))) { rr=highestRank[ranks]; if (rr!=0) { found=TRUE; qtricks=1; } else found=FALSE; } } if ((found)&&(depth!=localVar[thrId].iniDepth)) { for (k=0; k<=3; k++) posPoint->winRanks[depth][k]=0; if (rr!=0) posPoint->winRanks[depth][ss]=bitMapRank[rr]; if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { if (posPoint->tricksMAX+qtricks>=target) { return TRUE; } else if (trump==4) { if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss]) hh=hand; /* Hand to lead next trick */ else hh=partner[hand]; if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&& (posPoint->secondBest[ss].hand==hh)) { qtricks++; posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank]; if (posPoint->tricksMAX+qtricks>=target) { return TRUE; } } for (k=0; k<=3; k++) { if ((k!=ss)&&(posPoint->length[hh][k]!=0)) { /* Not lead suit, not void in suit */ if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0) &&(posPoint->length[partner[hh]][k]==0)) { qtricks+=counttable[posPoint->rankInSuit[hh][k]]; if (posPoint->tricksMAX+qtricks>=target) { return TRUE; } } else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) { qtricks++; posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank]; if (posPoint->tricksMAX+qtricks>=target) { return TRUE; } } } } } } else { /* MIN node */ if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) { return FALSE; } else if (trump==4) { if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss]) hh=hand; /* Hand to lead next trick */ else hh=partner[hand]; if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&& (posPoint->secondBest[ss].hand==hh)) { qtricks++; posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank]; if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) { return FALSE; } } for (k=0; k<=3; k++) { if ((k!=ss)&&(posPoint->length[hh][k]!=0)) { /* Not lead suit, not void in suit */ if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0) &&(posPoint->length[partner[hh]][k]==0)) { qtricks+=counttable[posPoint->rankInSuit[hh][k]]; if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) { return FALSE; } } else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) { qtricks++; posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank]; if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) { return FALSE; } } } } } } } } if ((posPoint->handRelFirst==0)&& (depth!=localVar[thrId].iniDepth)) { for (ss=0; ss<=3; ss++) { aggr[ss]=0; for (hh=0; hh<=3; hh++) aggr[ss]|=posPoint->rankInSuit[hh][ss]; posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss]; } tricks=depth>>2; suitLengths=0; for (ss=0; ss<=2; ss++) for (hh=0; hh<=3; hh++) { suitLengths<<=4; suitLengths|=posPoint->length[hh][ss]; } pp=SearchLenAndInsert(localVar[thrId].rootnp[tricks][hand], suitLengths, FALSE, &res, thrId); /* Find node that fits the suit lengths */ if (pp!=NULL) { np=pp->posSearchPoint; if (np==NULL) cardsP=NULL; else cardsP=FindSOP(posPoint, np, hand, target, tricks, &scoreFlag, thrId); if (cardsP!=NULL) { if (scoreFlag==1) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]= localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)cardsP->leastWin[ss]]; if (cardsP->bestMoveRank!=0) { localVar[thrId].bestMoveTT[depth].suit=cardsP->bestMoveSuit; localVar[thrId].bestMoveTT[depth].rank=cardsP->bestMoveRank; } #ifdef STAT c5[depth]++; if (scoreFlag==1) score1Counts[depth]++; else score0Counts[depth]++; if (depth==localVar[thrId].iniDepth) { fprintf(localVar[thrId].fp2, "score statistics:\n"); for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],c3[dd], c4[dd]); fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd], c7[dd], c8[dd]); } } #endif #ifdef TTDEBUG if (!suppressTTlog) { if (lastTTstorewinRanks[depth][ss]= localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)cardsP->leastWin[ss]]; if (cardsP->bestMoveRank!=0) { localVar[thrId].bestMoveTT[depth].suit=cardsP->bestMoveSuit; localVar[thrId].bestMoveTT[depth].rank=cardsP->bestMoveRank; } #ifdef STAT c6[depth]++; if (scoreFlag==1) score1Counts[depth]++; else score0Counts[depth]++; if (depth==localVar[thrId].iniDepth) { fprintf(localVar[thrId].fp2, "score statistics:\n"); for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], c4[dd]); fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd], c7[dd], c8[dd]); } } #endif #ifdef TTDEBUG if (!suppressTTlog) { if (lastTTstore=target) value=TRUE; else value=FALSE; for (ss=0; ss<=3; ss++) { posPoint->winRanks[depth][ss]=evalData.winRanks[ss]; #ifdef STAT c7[depth]++; if (value==1) score1Counts[depth]++; else score0Counts[depth]++; if (depth==localVar[thrId].iniDepth) { fprintf(localVar[thrId].fp2, "score statistics:\n"); for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], c4[dd]); fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd], c7[dd], c8[dd]); } } #endif } return value; } else { mply=&localVar[thrId].movePly[depth]; moveExists=MoveGen(posPoint, depth, trump, mply, thrId); /*#if 0*/ if ((posPoint->handRelFirst==3)&&(depth>=/*29*/33/*37*/) &&(depth!=localVar[thrId].iniDepth)) { /*localVar[thrId].movePly[depth].current=0;*/ mply->current=0; mexists=TRUE; ready=FALSE; while (mexists) { Make(posPoint, makeWinRank, depth, trump, mply, thrId); depth--; for (ss=0; ss<=3; ss++) { aggr[ss]=0; for (hh=0; hh<=3; hh++) aggr[ss]|=posPoint->rankInSuit[hh][ss]; posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss]; } tricks=depth>>2; hfirst=posPoint->first[depth]; suitLengths=0; for (ss=0; ss<=2; ss++) for (hh=0; hh<=3; hh++) { suitLengths<<=4; suitLengths|=posPoint->length[hh][ss]; } pp=SearchLenAndInsert(localVar[thrId].rootnp[tricks][hfirst], suitLengths, FALSE, &res, thrId); /* Find node that fits the suit lengths */ if (pp!=NULL) { np=pp->posSearchPoint; if (np==NULL) tempP=NULL; else tempP=FindSOP(posPoint, np, hfirst, target, tricks, &scoreFlag, thrId); if (tempP!=NULL) { if ((localVar[thrId].nodeTypeStore[hand]==MAXNODE)&&(scoreFlag==1)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth+1][ss]= localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)tempP->leastWin[ss]]; if (tempP->bestMoveRank!=0) { localVar[thrId].bestMoveTT[depth+1].suit=tempP->bestMoveSuit; localVar[thrId].bestMoveTT[depth+1].rank=tempP->bestMoveRank; } for (ss=0; ss<=3; ss++) posPoint->winRanks[depth+1][ss]|=makeWinRank[ss]; Undo(posPoint, depth+1, &localVar[thrId].movePly[depth+1],thrId); return TRUE; } else if ((localVar[thrId].nodeTypeStore[hand]==MINNODE)&&(scoreFlag==0)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth+1][ss]= localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)tempP->leastWin[ss]]; if (tempP->bestMoveRank!=0) { localVar[thrId].bestMoveTT[depth+1].suit=tempP->bestMoveSuit; localVar[thrId].bestMoveTT[depth+1].rank=tempP->bestMoveRank; } for (ss=0; ss<=3; ss++) posPoint->winRanks[depth+1][ss]|=makeWinRank[ss]; Undo(posPoint, depth+1, &localVar[thrId].movePly[depth+1], thrId); return FALSE; } else { localVar[thrId].movePly[depth+1].move[localVar[thrId].movePly[depth+1].current].weight+=100; ready=TRUE; } } } depth++; Undo(posPoint, depth, mply, thrId); if (ready) break; if (mply->current <= (mply->last-1)) { mply->current++; mexists=TRUE; } else mexists=FALSE; } if (ready) MergeSort(mply->last+1, mply->move); } /*#endif*/ mply->current=0; if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { value=FALSE; for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; while (moveExists) { Make(posPoint, makeWinRank, depth, trump, mply, thrId); /* Make current move */ assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); value=ABsearch(posPoint, target, depth-1, thrId); Undo(posPoint, depth, mply, thrId); /* Retract current move */ if (value==TRUE) { /* A cut-off? */ for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] | makeWinRank[ss]; mcurrent=mply->current; localVar[thrId].bestMove[depth]=mply->move[mcurrent]; goto ABexit; } for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=posPoint->winRanks[depth][ss] | posPoint->winRanks[depth-1][ss] | makeWinRank[ss]; moveExists=NextMove(posPoint, depth, mply, thrId); } } else { /* A minnode */ value=TRUE; for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; while (moveExists) { Make(posPoint, makeWinRank, depth, trump, mply, thrId); /* Make current move */ value=ABsearch(posPoint, target, depth-1, thrId); Undo(posPoint, depth, mply, thrId); /* Retract current move */ if (value==FALSE) { /* A cut-off? */ for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] | makeWinRank[ss]; mcurrent=mply->current; localVar[thrId].bestMove[depth]=mply->move[mcurrent]; goto ABexit; } for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=posPoint->winRanks[depth][ss] | posPoint->winRanks[depth-1][ss] | makeWinRank[ss]; moveExists=NextMove(posPoint, depth, mply, thrId); } } } ABexit: if (depth>=4) { if(posPoint->handRelFirst==0) { tricks=depth>>2; if (value) k=target; else k=target-1; if (depth!=localVar[thrId].iniDepth) BuildSOP(posPoint, tricks, hand, target, depth, value, k, thrId); if (localVar[thrId].clearTTflag) { /* Wipe out the TT dynamically allocated structures except for the initially allocated structures. Set the TT limits to the initial values. Reset TT array indices to zero. Reset memory chunk indices to zero. Set allocated memory to the initial value. */ /*localVar[thrId].fp2=fopen("dyn.txt", "a"); fprintf(localVar[thrId].fp2, "Clear TT:\n"); fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n", wcount, ncount, lcount); fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n", winSetSize, nodeSetSize, lenSetSize); fprintf(localVar[thrId].fp2, "\n"); fclose(localVar[thrId].fp2);*/ Wipe(thrId); localVar[thrId].winSetSizeLimit=WINIT; localVar[thrId].nodeSetSizeLimit=NINIT; localVar[thrId].lenSetSizeLimit=LINIT; localVar[thrId].lcount=0; localVar[thrId].allocmem=(localVar[thrId].lenSetSizeLimit+1)*sizeof(struct posSearchType); localVar[thrId].lenSetSize=0; localVar[thrId].posSearch=localVar[thrId].pl[localVar[thrId].lcount]; for (k=0; k<=13; k++) { for (hh=0; hh<=3; hh++) { localVar[thrId].rootnp[k][hh]=&localVar[thrId].posSearch[localVar[thrId].lenSetSize]; localVar[thrId].posSearch[localVar[thrId].lenSetSize].suitLengths=0; localVar[thrId].posSearch[localVar[thrId].lenSetSize].posSearchPoint=NULL; localVar[thrId].posSearch[localVar[thrId].lenSetSize].left=NULL; localVar[thrId].posSearch[localVar[thrId].lenSetSize].right=NULL; localVar[thrId].lenSetSize++; } } localVar[thrId].nodeSetSize=0; localVar[thrId].winSetSize=0; localVar[thrId].wcount=0; localVar[thrId].ncount=0; localVar[thrId].allocmem+=(localVar[thrId].winSetSizeLimit+1)*sizeof(struct winCardType); localVar[thrId].winCards=localVar[thrId].pw[localVar[thrId].wcount]; localVar[thrId].allocmem+=(localVar[thrId].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType); localVar[thrId].nodeCards=localVar[thrId].pn[localVar[thrId].ncount]; localVar[thrId].clearTTflag=FALSE; localVar[thrId].windex=-1; } } } #ifdef STAT c8[depth]++; if (value==1) score1Counts[depth]++; else score0Counts[depth]++; if (depth==localVar[thrId].iniDepth) { if (localVar[thrId].fp2==NULL) exit(0); fprintf(localVar[thrId].fp2, "\n"); fprintf(localVar[thrId].fp2, "top level cards:\n"); for (hh=0; hh<=3; hh++) { fprintf(localVar[thrId].fp2, "hand=%c\n", cardHand[hh]); for (ss=0; ss<=3; ss++) { fprintf(localVar[thrId].fp2, "suit=%c", cardSuit[ss]); for (rr=14; rr>=2; rr--) if (posPoint->rankInSuit[hh][ss] & bitMapRank[rr]) fprintf(localVar[thrId].fp2, " %c", cardRank[rr]); fprintf(localVar[thrId].fp2, "\n"); } fprintf(localVar[thrId].fp2, "\n"); } fprintf(localVar[thrId].fp2, "top level winning cards:\n"); for (ss=0; ss<=3; ss++) { fprintf(localVar[thrId].fp2, "suit=%c", cardSuit[ss]); for (rr=14; rr>=2; rr--) if (posPoint->winRanks[depth][ss] & bitMapRank[rr]) fprintf(localVar[thrId].fp2, " %c", cardRank[rr]); fprintf(localVar[thrId].fp2, "\n"); } fprintf(localVar[thrId].fp2, "\n"); fprintf(localVar[thrId].fp2, "\n"); fprintf(localVar[thrId].fp2, "score statistics:\n"); sumScore0Counts=0; sumScore1Counts=0; sumc1=0; sumc2=0; sumc3=0; sumc4=0; sumc5=0; sumc6=0; sumc7=0; sumc8=0; sumc9=0; for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { fprintf(localVar[thrId].fp2, "depth=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], c4[dd]); fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd], c7[dd], c8[dd]); sumScore0Counts=sumScore0Counts+score0Counts[dd]; sumScore1Counts=sumScore1Counts+score1Counts[dd]; sumc1=sumc1+c1[dd]; sumc2=sumc2+c2[dd]; sumc3=sumc3+c3[dd]; sumc4=sumc4+c4[dd]; sumc5=sumc5+c5[dd]; sumc6=sumc6+c6[dd]; sumc7=sumc7+c7[dd]; sumc8=sumc8+c8[dd]; sumc9=sumc9+c9[dd]; } fprintf(localVar[thrId].fp2, "\n"); fprintf(localVar[thrId].fp2, "score sum statistics:\n"); fprintf(localVar[thrId].fp2, "\n"); fprintf(localVar[thrId].fp2, "sumScore0Counts=%d sumScore1Counts=%d\n", sumScore0Counts, sumScore1Counts); fprintf(localVar[thrId].fp2, "nodeSetSize=%d winSetSize=%d\n", localVar[thrId].nodeSetSize, localVar[thrId].winSetSize); fprintf(localVar[thrId].fp2, "sumc1=%d sumc2=%d sumc3=%d sumc4=%d\n", sumc1, sumc2, sumc3, sumc4); fprintf(localVar[thrId].fp2, "sumc5=%d sumc6=%d sumc7=%d sumc8=%d sumc9=%d\n", sumc5, sumc6, sumc7, sumc8, sumc9); fprintf(localVar[thrId].fp2, "\n"); fprintf(localVar[thrId].fp2, "\n"); fprintf(localVar[thrId].fp2, "No of searched nodes per depth:\n"); for (dd=localVar[thrId].iniDepth; dd>=0; dd--) fprintf(localVar[thrId].fp2, "depth=%d nodes=%d\n", dd, localVar[thrId].no[dd]); fprintf(localVar[thrId].fp2, "\n"); fprintf(localVar[thrId].fp2, "Total nodes=%d\n", localVar[thrId].nodes); } #endif return value; } void Make(struct pos * posPoint, unsigned short int trickCards[4], int depth, int trump, struct movePlyType *mply, int thrId) { int r, s, t, u, w, firstHand; int suit, count, mcurr, h, q, done; struct moveType mo1, mo2; unsigned short aggr; assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); for (suit=0; suit<=3; suit++) trickCards[suit]=0; firstHand=posPoint->first[depth]; r=mply->current; if (posPoint->handRelFirst==3) { /* This hand is last hand */ mo1=mply->move[r]; mo2=posPoint->move[depth+1]; if (mo1.suit==mo2.suit) { if (mo1.rank>mo2.rank) { posPoint->move[depth]=mo1; posPoint->high[depth]=handId(firstHand, 3); } else { posPoint->move[depth]=posPoint->move[depth+1]; posPoint->high[depth]=posPoint->high[depth+1]; } } else if (mo1.suit==trump) { posPoint->move[depth]=mo1; posPoint->high[depth]=handId(firstHand, 3); } else { posPoint->move[depth]=posPoint->move[depth+1]; posPoint->high[depth]=posPoint->high[depth+1]; } /* Is the trick won by rank? */ suit=posPoint->move[depth].suit; count=0; mcurr=mply->current; if (mply->move[mcurr].suit==suit) count++; for (h=1; h<=3; h++) { mcurr=localVar[thrId].movePly[depth+h].current; if (localVar[thrId].movePly[depth+h].move[mcurr].suit==suit) count++; } if (localVar[thrId].nodeTypeStore[posPoint->high[depth]]==MAXNODE) posPoint->tricksMAX++; posPoint->first[depth-1]=posPoint->high[depth]; /* Defines who is first in the next move */ t=handId(firstHand, 3); posPoint->handRelFirst=0; /* Hand pointed to by posPoint->first will lead the next trick */ done=FALSE; for (s=3; s>=0; s--) { q=handId(firstHand, 3-s); /* Add the moves to removed ranks */ r=localVar[thrId].movePly[depth+s].current; w=localVar[thrId].movePly[depth+s].move[r].rank; u=localVar[thrId].movePly[depth+s].move[r].suit; posPoint->removedRanks[u]|=bitMapRank[w]; if (s==0) posPoint->rankInSuit[t][u]&=(~bitMapRank[w]); if ((w==posPoint->winner[u].rank)||(w==posPoint->secondBest[u].rank)) { aggr=0; for (h=0; h<=3; h++) aggr|=posPoint->rankInSuit[h][u]; posPoint->winner[u].rank=localVar[thrId].rel[aggr].absRank[1][u].rank; posPoint->winner[u].hand=localVar[thrId].rel[aggr].absRank[1][u].hand; posPoint->secondBest[u].rank=localVar[thrId].rel[aggr].absRank[2][u].rank; posPoint->secondBest[u].hand=localVar[thrId].rel[aggr].absRank[2][u].hand; } /* Determine win-ranked cards */ if ((q==posPoint->high[depth])&&(!done)) { done=TRUE; if (count>=2) { trickCards[u]=bitMapRank[w]; /* Mark ranks as winning if they are part of a sequence */ trickCards[u]|=localVar[thrId].movePly[depth+s].move[r].sequence; } } } } else if (posPoint->handRelFirst==0) { /* Is it the 1st hand? */ posPoint->first[depth-1]=firstHand; /* First hand is not changed in next move */ posPoint->high[depth]=firstHand; posPoint->move[depth]=mply->move[r]; t=firstHand; posPoint->handRelFirst=1; r=mply->current; u=mply->move[r].suit; w=mply->move[r].rank; posPoint->rankInSuit[t][u]&=(~bitMapRank[w]); } else { mo1=mply->move[r]; mo2=posPoint->move[depth+1]; r=mply->current; u=mply->move[r].suit; w=mply->move[r].rank; if (mo1.suit==mo2.suit) { if (mo1.rank>mo2.rank) { posPoint->move[depth]=mo1; posPoint->high[depth]=handId(firstHand, posPoint->handRelFirst); } else { posPoint->move[depth]=posPoint->move[depth+1]; posPoint->high[depth]=posPoint->high[depth+1]; } } else if (mo1.suit==trump) { posPoint->move[depth]=mo1; posPoint->high[depth]=handId(firstHand, posPoint->handRelFirst); } else { posPoint->move[depth]=posPoint->move[depth+1]; posPoint->high[depth]=posPoint->high[depth+1]; } t=handId(firstHand, posPoint->handRelFirst); posPoint->handRelFirst++; /* Current hand is stepped */ assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); posPoint->first[depth-1]=firstHand; /* First hand is not changed in next move */ posPoint->rankInSuit[t][u]&=(~bitMapRank[w]); } posPoint->length[t][u]--; #ifdef STAT localVar[thrId].no[depth]++; #endif return; } void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId) { int r, s, t, u, w, firstHand; assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); firstHand=posPoint->first[depth]; switch (posPoint->handRelFirst) { case 3: case 2: case 1: posPoint->handRelFirst--; break; case 0: posPoint->handRelFirst=3; } if (posPoint->handRelFirst==0) { /* 1st hand which won the previous trick */ t=firstHand; r=mply->current; u=mply->move[r].suit; w=mply->move[r].rank; } else if (posPoint->handRelFirst==3) { /* Last hand */ for (s=3; s>=0; s--) { /* Delete the moves from removed ranks */ r=localVar[thrId].movePly[depth+s].current; w=localVar[thrId].movePly[depth+s].move[r].rank; u=localVar[thrId].movePly[depth+s].move[r].suit; posPoint->removedRanks[u]&= (~bitMapRank[w]); if (w>posPoint->winner[u].rank) { posPoint->secondBest[u].rank=posPoint->winner[u].rank; posPoint->secondBest[u].hand=posPoint->winner[u].hand; posPoint->winner[u].rank=w; posPoint->winner[u].hand=handId(firstHand, 3-s); } else if (w>posPoint->secondBest[u].rank) { posPoint->secondBest[u].rank=w; posPoint->secondBest[u].hand=handId(firstHand, 3-s); } } t=handId(firstHand, 3); if (localVar[thrId].nodeTypeStore[posPoint->first[depth-1]]==MAXNODE) /* First hand of next trick is winner of the current trick */ posPoint->tricksMAX--; } else { t=handId(firstHand, posPoint->handRelFirst); r=mply->current; u=mply->move[r].suit; w=mply->move[r].rank; } posPoint->rankInSuit[t][u]|=bitMapRank[w]; posPoint->length[t][u]++; return; } struct evalType Evaluate(struct pos * posPoint, int trump, int thrId) { int s, smax=0, max, k, firstHand, count; struct evalType eval; firstHand=posPoint->first[0]; assert((firstHand >= 0)&&(firstHand <= 3)); for (s=0; s<=3; s++) eval.winRanks[s]=0; /* Who wins the last trick? */ if (trump!=4) { /* Highest trump card wins */ max=0; count=0; for (s=0; s<=3; s++) { if (posPoint->rankInSuit[s][trump]!=0) count++; if (posPoint->rankInSuit[s][trump]>max) { smax=s; max=posPoint->rankInSuit[s][trump]; } } if (max>0) { /* Trumpcard wins */ if (count>=2) eval.winRanks[trump]=max; if (localVar[thrId].nodeTypeStore[smax]==MAXNODE) goto maxexit; else goto minexit; } } /* Who has the highest card in the suit played by 1st hand? */ k=0; while (k<=3) { /* Find the card the 1st hand played */ if (posPoint->rankInSuit[firstHand][k]!=0) /* Is this the card? */ break; k++; } assert(k < 4); count=0; max=0; for (s=0; s<=3; s++) { if (posPoint->rankInSuit[s][k]!=0) count++; if (posPoint->rankInSuit[s][k]>max) { smax=s; max=posPoint->rankInSuit[s][k]; } } if (count>=2) eval.winRanks[k]=max; if (localVar[thrId].nodeTypeStore[smax]==MAXNODE) goto maxexit; else goto minexit; maxexit: eval.tricks=posPoint->tricksMAX+1; return eval; minexit: eval.tricks=posPoint->tricksMAX; return eval; } int QuickTricks(struct pos * posPoint, int hand, int depth, int target, int trump, int *result, int thrId) { int suit, sum, qtricks, commPartner, commRank=0, commSuit=-1, s/*, found=FALSE*/; int opps, res; int countLho, countRho, countPart, countOwn, lhoTrumpRanks, rhoTrumpRanks; int cutoff, ss, rr, lowestQtricks=0/*, count=0*//*, ruff=FALSE*/; int QtricksLeadHandNT(int hand, struct pos *posPoint, int cutoff, int depth, int countLho, int countRho, int *lhoTrumpRanks, int *rhoTrumpRanks, int commPartner, int commSuit, int countOwn, int countPart, int suit, int qtricks, int trump, int *res); int QtricksLeadHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, int countPart, int suit, int qtricks, int trump, int *res); int QuickTricksPartnerHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId); int QuickTricksPartnerHandNT(int hand, struct pos *posPoint, int cutoff, int depth, int countLho, int countRho, int countOwn, int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId); *result=TRUE; qtricks=0; for (s=0; s<=3; s++) posPoint->winRanks[depth][s]=0; if ((depth<=0)||(depth==localVar[thrId].iniDepth)) { *result=FALSE; return qtricks; } if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) cutoff=target-posPoint->tricksMAX; else cutoff=posPoint->tricksMAX-target+(depth>>2)+2; commPartner=FALSE; for (s=0; s<=3; s++) { if ((trump!=4)&&(trump!=s)) { if (posPoint->winner[s].hand==partner[hand]) { /* Partner has winning card */ if (posPoint->rankInSuit[hand][s]!=0) { /* Own hand has card in suit */ if (((posPoint->rankInSuit[lho[hand]][s]!=0) || /* LHO not void */ (posPoint->rankInSuit[lho[hand]][trump]==0)) /* LHO has no trump */ && ((posPoint->rankInSuit[rho[hand]][s]!=0) || /* RHO not void */ (posPoint->rankInSuit[rho[hand]][trump]==0))) { /* RHO has no trump */ commPartner=TRUE; commSuit=s; commRank=posPoint->winner[s].rank; break; } } } else if (posPoint->secondBest[s].hand==partner[hand]) { if ((posPoint->winner[s].hand==hand)&& (posPoint->length[hand][s]>=2)&&(posPoint->length[partner[hand]][s]>=2)) { if (((posPoint->rankInSuit[lho[hand]][s]!=0) || (posPoint->rankInSuit[lho[hand]][trump]==0)) && ((posPoint->rankInSuit[rho[hand]][s]!=0) || (posPoint->rankInSuit[rho[hand]][trump]==0))) { commPartner=TRUE; commSuit=s; commRank=posPoint->secondBest[s].rank; break; } } } } else if (trump==4) { if (posPoint->winner[s].hand==partner[hand]) { /* Partner has winning card */ if (posPoint->rankInSuit[hand][s]!=0) { /* Own hand has card in suit */ commPartner=TRUE; commSuit=s; commRank=posPoint->winner[s].rank; break; } } else if (posPoint->secondBest[s].hand==partner[hand]) { if ((posPoint->winner[s].hand==hand)&& (posPoint->length[hand][s]>=2)&&(posPoint->length[partner[hand]][s]>=2)) { commPartner=TRUE; commSuit=s; commRank=posPoint->secondBest[s].rank; break; } } } } if ((trump!=4) && (!commPartner) && (posPoint->rankInSuit[hand][trump]!=0) && (posPoint->winner[trump].hand==partner[hand])) { commPartner=TRUE; commSuit=trump; commRank=posPoint->winner[trump].rank; } if (trump!=4) { suit=trump; lhoTrumpRanks=posPoint->length[lho[hand]][trump]; rhoTrumpRanks=posPoint->length[rho[hand]][trump]; } else suit=0; do { countOwn=posPoint->length[hand][suit]; countLho=posPoint->length[lho[hand]][suit]; countRho=posPoint->length[rho[hand]][suit]; countPart=posPoint->length[partner[hand]][suit]; opps=countLho | countRho; if (!opps && (countPart==0)) { if (countOwn==0) { /* Continue with next suit. */ if ((trump!=4)&&(trump!=suit)) { suit++; if ((trump!=4) && (suit==trump)) suit++; } else { if ((trump!=4) && (trump==suit)) { if (trump==0) suit=1; else suit=0; } else suit++; } continue; } /* Long tricks when only leading hand have cards in the suit. */ if ((trump!=4) && (trump!=suit)) { if ((lhoTrumpRanks==0) && (rhoTrumpRanks==0)) { qtricks+=countOwn; if (qtricks>=cutoff) return qtricks; suit++; if ((trump!=4) && (suit==trump)) suit++; continue; } else { suit++; if ((trump!=4) && (suit==trump)) suit++; continue; } } else { qtricks+=countOwn; if (qtricks>=cutoff) return qtricks; if ((trump!=4) && (suit==trump)) { if (trump==0) suit=1; else suit=0; } else { suit++; if ((trump!=4) && (suit==trump)) suit++; } continue; } } else { if (!opps && (trump!=4) && (suit==trump)) { /* The partner but not the opponents have cards in the trump suit. */ sum=Max(countOwn, countPart); for (s=0; s<=3; s++) { if ((sum>0)&&(s!=trump)&&(countOwn>=countPart)&&(posPoint->length[hand][s]>0)&& (posPoint->length[partner[hand]][s]==0)) { sum++; break; } } /* If the additional trick by ruffing causes a cutoff. (qtricks not incremented.) */ if (sum>=cutoff) return sum; } else if (!opps) { /* The partner but not the opponents have cards in the suit. */ sum=Min(countOwn,countPart); if (trump==4) { if (sum>=cutoff) return sum; } else if ((suit!=trump)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { if (sum>=cutoff) return sum; } } if (commPartner) { if (!opps && (countOwn==0)) { if ((trump!=4) && (trump!=suit)) { if ((lhoTrumpRanks==0) && (rhoTrumpRanks==0)) { qtricks+=countPart; posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; if (qtricks>=cutoff) return qtricks; suit++; if ((trump!=4) && (suit==trump)) suit++; continue; } else { suit++; if ((trump!=4) && (suit==trump)) suit++; continue; } } else { qtricks+=countPart; posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; if (qtricks>=cutoff) return qtricks; if ((trump!=4) && (suit==trump)) { if (trump==0) suit=1; else suit=0; } else { suit++; if ((trump!=4) && (suit==trump)) suit++; } continue; } } else { if (!opps && (trump!=4) && (suit==trump)) { sum=Max(countOwn, countPart); for (s=0; s<=3; s++) { if ((sum>0)&&(s!=trump)&&(countOwn<=countPart)&&(posPoint->length[partner[hand]][s]>0)&& (posPoint->length[hand][s]==0)) { sum++; break; } } if (sum>=cutoff) { posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; return sum; } } else if (!opps) { sum=Min(countOwn,countPart); if (trump==4) { if (sum>=cutoff) return sum; } else if ((suit!=trump)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { if (sum>=cutoff) return sum; } } } } } if (posPoint->winner[suit].rank==0) { if ((trump!=4) && (suit==trump)) { if (trump==0) suit=1; else suit=0; } else { suit++; if ((trump!=4) && (suit==trump)) suit++; } continue; } if (posPoint->winner[suit].hand==hand) { if ((trump!=4)&&(trump!=suit)) { qtricks=QtricksLeadHandTrump(hand, posPoint, cutoff, depth, countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, countOwn, countPart, suit, qtricks, trump, &res); if (res==1) return qtricks; else if (res==2) { suit++; if ((trump!=4) && (suit==trump)) suit++; continue; } } else { qtricks=QtricksLeadHandNT(hand, posPoint, cutoff, depth, countLho, countRho, &lhoTrumpRanks, &rhoTrumpRanks, commPartner, commSuit, countOwn, countPart, suit, qtricks, trump, &res); if (res==1) return qtricks; else if (res==2) { if ((trump!=4) && (trump==suit)) { if (trump==0) suit=1; else suit=0; } else suit++; continue; } } } /* It was not possible to take a quick trick by own winning card in the suit */ else { /* Partner winning card? */ if ((posPoint->winner[suit].hand==partner[hand])&&(1/*countPart>0*/)) { /* Winner found at partner*/ if (commPartner) { /* There is communication with the partner */ if ((trump!=4)&&(trump!=suit)) { qtricks=QuickTricksPartnerHandTrump(hand, posPoint, cutoff, depth, countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, countOwn, countPart, suit, qtricks, commSuit, commRank, trump, &res, thrId); if (res==1) return qtricks; else if (res==2) { suit++; if ((trump!=4) && (suit==trump)) suit++; continue; } } else { qtricks=QuickTricksPartnerHandNT(hand, posPoint, cutoff, depth, countLho, countRho, countOwn, countPart, suit, qtricks, commSuit, commRank, trump, &res, thrId); if (res==1) return qtricks; else if (res==2) { if ((trump!=4) && (trump==suit)) { if (trump==0) suit=1; else suit=0; } else suit++; continue; } } } } } if ((trump!=4) &&(suit!=trump)&& (countOwn>0)&&(lowestQtricks==0)&& ((qtricks==0)||((posPoint->winner[suit].hand!=hand)&& (posPoint->winner[suit].hand!=partner[hand])&& (posPoint->winner[trump].hand!=hand)&& (posPoint->winner[trump].hand!=partner[hand])))) { if ((countPart==0)&&(posPoint->length[partner[hand]][trump]>0)) { if (((countRho>0)||(posPoint->length[rho[hand]][trump]==0))&& ((countLho>0)||(posPoint->length[lho[hand]][trump]==0))) { lowestQtricks=1; if (1>=cutoff) return 1; suit++; if ((trump!=4) && (suit==trump)) suit++; continue; } else if ((countRho==0)&&(countLho==0)) { if ((posPoint->rankInSuit[lho[hand]][trump] | posPoint->rankInSuit[rho[hand]][trump]) < posPoint->rankInSuit[partner[hand]][trump]) { lowestQtricks=1; rr=highestRank[posPoint->rankInSuit[partner[hand]][trump]]; if (rr!=0) { posPoint->winRanks[depth][trump]|=bitMapRank[rr]; if (1>=cutoff) return 1; } } suit++; if ((trump!=4) && (suit==trump)) suit++; continue; } else if (countLho==0) { if (posPoint->rankInSuit[lho[hand]][trump] < posPoint->rankInSuit[partner[hand]][trump]) { lowestQtricks=1; for (rr=14; rr>=2; rr--) { if ((posPoint->rankInSuit[partner[hand]][trump] & bitMapRank[rr])!=0) { posPoint->winRanks[depth][trump]|=bitMapRank[rr]; break; } } if (1>=cutoff) return 1; } suit++; if ((trump!=4) && (suit==trump)) suit++; continue; } else if (countRho==0) { if (posPoint->rankInSuit[rho[hand]][trump] < posPoint->rankInSuit[partner[hand]][trump]) { lowestQtricks=1; for (rr=14; rr>=2; rr--) { if ((posPoint->rankInSuit[partner[hand]][trump] & bitMapRank[rr])!=0) { posPoint->winRanks[depth][trump]|=bitMapRank[rr]; break; } } if (1>=cutoff) return 1; } suit++; if ((trump!=4) && (suit==trump)) suit++; continue; } } } if (qtricks>=cutoff) return qtricks; if ((trump!=4) && (suit==trump)) { if (trump==0) suit=1; else suit=0; } else { suit++; if ((trump!=4) && (suit==trump)) suit++; } } while (suit<=3); if (qtricks==0) { if ((trump==4)||(posPoint->winner[trump].hand==-1)) { for (ss=0; ss<=3; ss++) { if (posPoint->winner[ss].hand==-1) continue; if (posPoint->length[hand][ss]>0) { posPoint->winRanks[depth][ss]= bitMapRank[posPoint->winner[ss].rank]; } } if (localVar[thrId].nodeTypeStore[hand]!=MAXNODE) cutoff=target-posPoint->tricksMAX; else cutoff=posPoint->tricksMAX-target+(depth>>2)+2; if (1>=cutoff) return 0; } } *result=FALSE; return qtricks; } int QtricksLeadHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, int countPart, int suit, int qtricks, int trump, int *res) { /* res=0 Continue with same suit. res=1 Cutoff. res=2 Continue with next suit. */ int qt; *res=1; qt=qtricks; if (((countLho!=0) || (lhoTrumpRanks==0)) && ((countRho!=0) || (rhoTrumpRanks==0))) { posPoint->winRanks[depth][suit]|= bitMapRank[posPoint->winner[suit].rank]; qt++; if (qt>=cutoff) return qt; if ((countLho<=1)&&(countRho<=1)&&(countPart<=1)&& (lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { qt+=countOwn-1; if (qt>=cutoff) return qt; *res=2; return qt; } } if (posPoint->secondBest[suit].hand==hand) { if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { posPoint->winRanks[depth][suit]|= bitMapRank[posPoint->secondBest[suit].rank]; qt++; if (qt>=cutoff) return qt; if ((countLho<=2)&&(countRho<=2)&&(countPart<=2)) { qt+=countOwn-2; if (qt>=cutoff) return qt; *res=2; return qt; } /*else { aggr=0; for (k=0; k<=3; k++) aggr|=posPoint->rankInSuit[k][suit]; if (rel[aggr].absRank[3][suit].hand==hand) { qt++; posPoint->winRanks[depth][suit]|= bitMapRank[rel[aggr].absRank[3][suit].rank]; if (qt>=cutoff) return qt; if ((countLho<=3)&&(countRho<=3)&&(countPart<=3)) { qt+=countOwn-3; if (qt>=cutoff) return qt; } *res=2; return qt; } }*/ } } else if ((posPoint->secondBest[suit].hand==partner[hand]) &&(countOwn>1)&&(countPart>1)) { /* Second best at partner and suit length of own hand and partner > 1 */ if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { posPoint->winRanks[depth][suit]|= bitMapRank[posPoint->secondBest[suit].rank]; qt++; if (qt>=cutoff) return qt; if ((countLho<=2)&&(countRho<=2)&&((countPart<=2)||(countOwn<=2))) { qt+=Max(countOwn-2, countPart-2); if (qt>=cutoff) return qt; *res=2; return qt; } } } *res=0; return qt; } int QtricksLeadHandNT(int hand, struct pos *posPoint, int cutoff, int depth, int countLho, int countRho, int *lhoTrumpRanks, int *rhoTrumpRanks, int commPartner, int commSuit, int countOwn, int countPart, int suit, int qtricks, int trump, int *res) { /* res=0 Continue with same suit. res=1 Cutoff. res=2 Continue with next suit. */ int qt; *res=1; qt=qtricks; posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank]; qt++; if (qt>=cutoff) return qt; if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) { /*if (trump==suit) {*/ (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1); (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1); } if ((countLho<=1)&&(countRho<=1)&&(countPart<=1)) { qt+=countOwn-1; if (qt>=cutoff) return qt; *res=2; return qt; } if (posPoint->secondBest[suit].hand==hand) { posPoint->winRanks[depth][suit]|= bitMapRank[posPoint->secondBest[suit].rank]; qt++; if (qt>=cutoff) return qt; if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) { /*if (trump==suit) {*/ (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1); (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1); } if ((countLho<=2)&&(countRho<=2)&&(countPart<=2)) { qt+=countOwn-2; if (qt>=cutoff) return qt; *res=2; return qt; } /*else { aggr=0; for (k=0; k<=3; k++) aggr|=posPoint->rankInSuit[k][suit]; if (rel[aggr].absRank[3][suit].hand==hand) { qt++; posPoint->winRanks[depth][suit]|= bitMapRank[rel[aggr].absRank[3][suit].rank]; if (qt>=cutoff) return qt; if ((countLho<=3)&&(countRho<=3)&&(countPart<=3)) { qt+=countOwn-3; if (qt>=cutoff) return qt; } *res=2; return qt; } }*/ } else if ((posPoint->secondBest[suit].hand==partner[hand]) &&(countOwn>1)&&(countPart>1)) { /* Second best at partner and suit length of own hand and partner > 1 */ posPoint->winRanks[depth][suit]|= bitMapRank[posPoint->secondBest[suit].rank]; qt++; if (qt>=cutoff) return qt; if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) { /*if (trump==suit) {*/ (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1); (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1); } if ((countLho<=2)&&(countRho<=2)&&((countPart<=2)||(countOwn<=2))) { qt+=Max(countOwn-2,countPart-2); if (qt>=cutoff) return qt; *res=2; return qt; } /*else if (countPart>2) { aggr=0; for (k=0; k<=3; k++) aggr|=posPoint->rankInSuit[k][suit]; if (rel[aggr].absRank[3][suit].hand==hand) { qt++; posPoint->winRanks[depth][suit]|= bitMapRank[rel[aggr].absRank[3][suit].rank]; if (qt>=cutoff) return qt; *res=2; return qt; } }*/ } *res=0; return qt; } int QuickTricksPartnerHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId) { /* res=0 Continue with same suit. res=1 Cutoff. res=2 Continue with next suit. */ int qt, k; unsigned short ranks; *res=1; qt=qtricks; if (((countLho!=0) || (lhoTrumpRanks==0)) && ((countRho!=0) || (rhoTrumpRanks==0))) { posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank]; posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; qt++; /* A trick can be taken */ if (qt>=cutoff) return qt; if ((countLho<=1)&&(countRho<=1)&&(countOwn<=1)&&(lhoTrumpRanks==0)&& (rhoTrumpRanks==0)) { qt+=countPart-1; if (qt>=cutoff) return qt; *res=2; return qt; } } if (posPoint->secondBest[suit].hand==partner[hand]) { /* Second best found in partners hand */ if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { /* Opponents have no trump */ posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; qt++; if (qt>=cutoff) return qt; if ((countLho<=2)&&(countRho<=2)&&(countOwn<=2)) { qt+=countPart-2; if (qt>=cutoff) return qt; *res=2; return qt; } } } else if ((posPoint->secondBest[suit].hand==hand)&&(countPart>1)&&(countOwn>1)) { /* Second best found in own hand and suit lengths of own hand and partner > 1*/ if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { /* Opponents have no trump */ posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; qt++; if (qt>=cutoff) return qt; if ((countLho<=2)&&(countRho<=2)&&((countOwn<=2)||(countPart<=2))) { qt+=Max(countPart-2,countOwn-2); if (qt>=cutoff) return qt; *res=2; return qt; } } } else if ((suit==commSuit)&&(posPoint->secondBest[suit].hand==lho[hand])&& ((countLho>=2)||(lhoTrumpRanks==0))&&((countRho>=2)||(rhoTrumpRanks==0))) { ranks=0; for (k=0; k<=3; k++) ranks|=posPoint->rankInSuit[k][suit]; if (localVar[thrId].rel[ranks].absRank[3][suit].hand==partner[hand]) { posPoint->winRanks[depth][suit]|=bitMapRank[localVar[thrId].rel[ranks].absRank[3][suit].rank]; posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; qt++; if (qt>=cutoff) return qt; if ((countOwn<=2)&&(countLho<=2)&&(countRho<=2)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { qt+=countPart-2; if (qt>=cutoff) return qt; } } } *res=0; return qt; } int QuickTricksPartnerHandNT(int hand, struct pos *posPoint, int cutoff, int depth, int countLho, int countRho, int countOwn, int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId) { int qt, k/*, found, rr*/; unsigned short ranks; *res=1; qt=qtricks; posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank]; posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; qt++; if (qt>=cutoff) return qt; if ((countLho<=1)&&(countRho<=1)&&(countOwn<=1)) { qt+=countPart-1; if (qt>=cutoff) return qt; *res=2; return qt; } if ((posPoint->secondBest[suit].hand==partner[hand])&&(1/*countPart>0*/)) { /* Second best found in partners hand */ posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; qt++; if (qt>=cutoff) return qt; if ((countLho<=2)&&(countRho<=2)&&(countOwn<=2)) { qt+=countPart-2; if (qt>=cutoff) return qt; *res=2; return qt; } } else if ((posPoint->secondBest[suit].hand==hand) &&(countPart>1)&&(countOwn>1)) { /* Second best found in own hand and own and partner's suit length > 1 */ posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; qt++; if (qt>=cutoff) return qt; if ((countLho<=2)&&(countRho<=2)&&((countOwn<=2)||(countPart<=2))) { qt+=Max(countPart-2,countOwn-2); if (qt>=cutoff) return qt; *res=2; return qt; } } else if ((suit==commSuit)&&(posPoint->secondBest[suit].hand==lho[hand])) { ranks=0; for (k=0; k<=3; k++) ranks=ranks | posPoint->rankInSuit[k][suit]; if (localVar[thrId].rel[ranks].absRank[3][suit].hand==partner[hand]) { posPoint->winRanks[depth][suit]|=bitMapRank[localVar[thrId].rel[ranks].absRank[3][suit].rank]; qt++; if (qt>=cutoff) return qt; if ((countOwn<=2)&&(countLho<=2)&&(countRho<=2)) { qtricks+=countPart-2; if (qt>=cutoff) return qt; } } } *res=0; return qt; } int LaterTricksMIN(struct pos *posPoint, int hand, int depth, int target, int trump, int thrId) { int hh, ss, k, h, sum=0; unsigned short aggr; if ((trump==4)||(posPoint->winner[trump].rank==0)) { for (ss=0; ss<=3; ss++) { hh=posPoint->winner[ss].hand; if (hh!=-1) { if (localVar[thrId].nodeTypeStore[hh]==MAXNODE) sum+=Max(posPoint->length[hh][ss], posPoint->length[partner[hh]][ss]); } } if ((posPoint->tricksMAX+sum0)&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { if ((posPoint->tricksMAX+(depth>>2)winner[ss].hand==-1) posPoint->winRanks[depth][ss]=0; else if (localVar[thrId].nodeTypeStore[posPoint->winner[ss].hand]==MINNODE) { if ((posPoint->rankInSuit[partner[posPoint->winner[ss].hand]][ss]==0)&& (posPoint->rankInSuit[lho[posPoint->winner[ss].hand]][ss]==0)&& (posPoint->rankInSuit[rho[posPoint->winner[ss].hand]][ss]==0)) posPoint->winRanks[depth][ss]=0; else posPoint->winRanks[depth][ss]=bitMapRank[posPoint->winner[ss].rank]; } else posPoint->winRanks[depth][ss]=0; } return FALSE; } } } else if ((trump!=4) && (posPoint->winner[trump].rank!=0) && (localVar[thrId].nodeTypeStore[posPoint->winner[trump].hand]==MINNODE)) { if ((posPoint->length[hand][trump]==0)&& (posPoint->length[partner[hand]][trump]==0)) { if (((posPoint->tricksMAX+(depth>>2)+1- Max(posPoint->length[lho[hand]][trump], posPoint->length[rho[hand]][trump]))0)&&(depth!=localVar[thrId].iniDepth)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; return FALSE; } } else if (((posPoint->tricksMAX+(depth>>2))0)&&(depth!=localVar[thrId].iniDepth)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; posPoint->winRanks[depth][trump]= bitMapRank[posPoint->winner[trump].rank]; return FALSE; } else { hh=posPoint->secondBest[trump].hand; if (hh!=-1) { if ((localVar[thrId].nodeTypeStore[hh]==MINNODE)&&(posPoint->secondBest[trump].rank!=0)) { if (((posPoint->length[hh][trump]>1) || (posPoint->length[partner[hh]][trump]>1))&& ((posPoint->tricksMAX+(depth>>2)-1)0) &&(depth!=localVar[thrId].iniDepth)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; posPoint->winRanks[depth][trump]= bitMapRank[posPoint->secondBest[trump].rank] ; return FALSE; } } } } } else if (trump!=4) { hh=posPoint->secondBest[trump].hand; if (hh!=-1) { if ((localVar[thrId].nodeTypeStore[hh]==MINNODE)&& (posPoint->length[hh][trump]>1)) { if (posPoint->winner[trump].hand==rho[hh]) { if (((posPoint->tricksMAX+(depth>>2))0)&&(depth!=localVar[thrId].iniDepth)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; posPoint->winRanks[depth][trump]= bitMapRank[posPoint->secondBest[trump].rank]; return FALSE; } } else { aggr=0; for (k=0; k<=3; k++) aggr|=posPoint->rankInSuit[k][trump]; h=localVar[thrId].rel[aggr].absRank[3][trump].hand; if (h!=-1) { if ((localVar[thrId].nodeTypeStore[h]==MINNODE)&& ((posPoint->tricksMAX+(depth>>2))0)&&(depth!=localVar[thrId].iniDepth)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; posPoint->winRanks[depth][trump]= bitMapRank[localVar[thrId].rel[aggr].absRank[3][trump].rank]; return FALSE; } } } } } } return TRUE; } int LaterTricksMAX(struct pos *posPoint, int hand, int depth, int target, int trump, int thrId) { int hh, ss, k, h, sum=0; unsigned short aggr; if ((trump==4)||(posPoint->winner[trump].rank==0)) { for (ss=0; ss<=3; ss++) { hh=posPoint->winner[ss].hand; if (hh!=-1) { if (localVar[thrId].nodeTypeStore[hh]==MINNODE) sum+=Max(posPoint->length[hh][ss], posPoint->length[partner[hh]][ss]); } } if ((posPoint->tricksMAX+(depth>>2)+1-sum>=target)&& (sum>0)&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { if ((posPoint->tricksMAX+1>=target)) { for (ss=0; ss<=3; ss++) { if (posPoint->winner[ss].hand==-1) posPoint->winRanks[depth][ss]=0; else if (localVar[thrId].nodeTypeStore[posPoint->winner[ss].hand]==MAXNODE) { if ((posPoint->rankInSuit[partner[posPoint->winner[ss].hand]][ss]==0)&& (posPoint->rankInSuit[lho[posPoint->winner[ss].hand]][ss]==0)&& (posPoint->rankInSuit[rho[posPoint->winner[ss].hand]][ss]==0)) posPoint->winRanks[depth][ss]=0; else posPoint->winRanks[depth][ss]=bitMapRank[posPoint->winner[ss].rank]; } else posPoint->winRanks[depth][ss]=0; } return TRUE; } } } else if ((trump!=4) && (posPoint->winner[trump].rank!=0) && (localVar[thrId].nodeTypeStore[posPoint->winner[trump].hand]==MAXNODE)) { if ((posPoint->length[hand][trump]==0)&& (posPoint->length[partner[hand]][trump]==0)) { if (((posPoint->tricksMAX+Max(posPoint->length[lho[hand]][trump], posPoint->length[rho[hand]][trump]))>=target) &&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; return TRUE; } } else if (((posPoint->tricksMAX+1)>=target) &&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; posPoint->winRanks[depth][trump]= bitMapRank[posPoint->winner[trump].rank]; return TRUE; } else { hh=posPoint->secondBest[trump].hand; if (hh!=-1) { if ((localVar[thrId].nodeTypeStore[hh]==MAXNODE)&&(posPoint->secondBest[trump].rank!=0)) { if (((posPoint->length[hh][trump]>1) || (posPoint->length[partner[hh]][trump]>1))&& ((posPoint->tricksMAX+2)>=target)&&(depth>0) &&(depth!=localVar[thrId].iniDepth)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; posPoint->winRanks[depth][trump]= bitMapRank[posPoint->secondBest[trump].rank]; return TRUE; } } } } } else if (trump!=4) { hh=posPoint->secondBest[trump].hand; if (hh!=-1) { if ((localVar[thrId].nodeTypeStore[hh]==MAXNODE)&& (posPoint->length[hh][trump]>1)) { if (posPoint->winner[trump].hand==rho[hh]) { if (((posPoint->tricksMAX+1)>=target)&&(depth>0) &&(depth!=localVar[thrId].iniDepth)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; posPoint->winRanks[depth][trump]= bitMapRank[posPoint->secondBest[trump].rank] ; return TRUE; } } else { aggr=0; for (k=0; k<=3; k++) aggr|=posPoint->rankInSuit[k][trump]; h=localVar[thrId].rel[aggr].absRank[3][trump].hand; if (h!=-1) { if ((localVar[thrId].nodeTypeStore[h]==MAXNODE)&& ((posPoint->tricksMAX+1)>=target)&&(depth>0) &&(depth!=localVar[thrId].iniDepth)) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; posPoint->winRanks[depth][trump]= bitMapRank[localVar[thrId].rel[aggr].absRank[3][trump].rank]; return TRUE; } } } } } } return FALSE; } int MoveGen(struct pos * posPoint, int depth, int trump, struct movePlyType *mply, int thrId) { int suit, k, m, r, s, t, q, first, state; unsigned short ris; int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, unsigned short notVoidInSuit, int trump, int thrId); int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, unsigned short notVoidInSuit, int thrId); for (k=0; k<4; k++) localVar[thrId].lowestWin[depth][k]=0; m=0; r=posPoint->handRelFirst; assert((r>=0)&&(r<=3)); first=posPoint->first[depth]; q=handId(first, r); if (r!=0) { s=localVar[thrId].movePly[depth+r].current; /* Current move of first hand */ t=localVar[thrId].movePly[depth+r].move[s].suit; /* Suit played by first hand */ ris=posPoint->rankInSuit[q][t]; if (ris!=0) { /* Not first hand and not void in suit */ k=14; state=MOVESVALID; while (k>=2) { if ((ris & bitMapRank[k])&&(state==MOVESVALID)) { /* Only first move in sequence is generated */ mply->move[m].suit=t; mply->move[m].rank=k; mply->move[m].sequence=0; m++; state=MOVESLOCKED; } else if (state==MOVESLOCKED) if ((posPoint->removedRanks[t] & bitMapRank[k])==0) { if ((ris & bitMapRank[k])==0) /* If the card still exists and it is not in own hand */ state=MOVESVALID; else /* If the card still exists and it is in own hand */ mply->move[m-1].sequence|=bitMapRank[k]; } k--; } if (m!=1) { if ((trump!=4)&&(posPoint->winner[trump].rank!=0)) { for (k=0; k<=m-1; k++) mply->move[k].weight=WeightAllocTrump(posPoint, &(mply->move[k]), depth, ris, trump, thrId); } else { for (k=0; k<=m-1; k++) mply->move[k].weight=WeightAllocNT(posPoint, &(mply->move[k]), depth, ris, thrId); } } mply->last=m-1; if (m!=1) MergeSort(m, mply->move); if (depth!=localVar[thrId].iniDepth) return m; else { m=AdjustMoveList(thrId); return m; } } } /* First hand or void in suit */ for (suit=0; suit<=3; suit++) { k=14; state=MOVESVALID; while (k>=2) { if ((posPoint->rankInSuit[q][suit] & bitMapRank[k])&& (state==MOVESVALID)) { /* Only first move in sequence is generated */ mply->move[m].suit=suit; mply->move[m].rank=k; mply->move[m].sequence=0; m++; state=MOVESLOCKED; } else if (state==MOVESLOCKED) if ((posPoint->removedRanks[suit] & bitMapRank[k])==0) { if ((posPoint->rankInSuit[q][suit] & bitMapRank[k])==0) /* If the card still exists and it is not in own hand */ state=MOVESVALID; else /* If the card still exists and it is in own hand */ mply->move[m-1].sequence|=bitMapRank[k]; } k--; } } if ((trump!=4)&&(posPoint->winner[trump].rank!=0)) { for (k=0; k<=m-1; k++) mply->move[k].weight=WeightAllocTrump(posPoint, &(mply->move[k]), depth, 0/*ris*/, trump, thrId); } else { for (k=0; k<=m-1; k++) mply->move[k].weight=WeightAllocNT(posPoint, &(mply->move[k]), depth, 0/*ris*/, thrId); } mply->last=m-1; if (m!=1) MergeSort(m, mply->move); if (depth!=localVar[thrId].iniDepth) return m; else { m=AdjustMoveList(thrId); return m; } } int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, unsigned short notVoidInSuit, int thrId) { int weight=0, k, l, kk, ll, suit, suitAdd=0, leadSuit; int suitWeightDelta, first, q; int rRank, thirdBestHand; int winMove=FALSE; /* If winMove is true, current move can win the current trick. */ unsigned short suitCount, suitCountLH, suitCountRH, aggr; int countLH, countRH; first=posPoint->first[depth]; q=handId(first, posPoint->handRelFirst); suit=mp->suit; aggr=0; for (k=0; k<=3; k++) aggr|=posPoint->rankInSuit[k][suit]; rRank=localVar[thrId].rel[aggr].relRank[mp->rank][suit]; switch (posPoint->handRelFirst) { case 0: thirdBestHand=localVar[thrId].rel[aggr].absRank[3][suit].hand; suitCount=posPoint->length[q][suit]; suitCountLH=posPoint->length[lho[q]][suit]; suitCountRH=posPoint->length[rho[q]][suit]; if (suitCountLH!=0) { countLH=(suitCountLH<<2); } else countLH=depth+4; if (suitCountRH!=0) { countRH=(suitCountRH<<2); } else countRH=depth+4; /* Discourage a suit selection where the search tree appears larger than for the altenative suits: the search is estimated to be small when the added number of alternative cards to play for the opponents is small. */ suitWeightDelta=-((countLH+countRH)<<5)/19; if (posPoint->winner[suit].rank==mp->rank) winMove=TRUE; else if (posPoint->rankInSuit[partner[first]][suit] > (posPoint->rankInSuit[lho[first]][suit] | posPoint->rankInSuit[rho[first]][suit])) { winMove=TRUE; } if (winMove) { /* Discourage suit if RHO has second best card. Exception: RHO has singleton. */ if (posPoint->secondBest[suit].hand==rho[q]) { if (suitCountRH!=1) suitWeightDelta-=7; } /* Encourage playing suit if LHO has second highest rank. */ else if (posPoint->secondBest[suit].hand==lho[q]) suitWeightDelta+=14; /* Higher weight if also second best rank is present on current side to play, or if second best is a singleton at LHO or RHO. */ if (((posPoint->secondBest[suit].hand!=lho[first]) ||(suitCountLH==1))&& ((posPoint->secondBest[suit].hand!=rho[first]) ||(suitCountRH==1))) weight=suitWeightDelta+41/*48*/+rRank; /* Encourage playing second highest rank if hand also has third highest rank. */ else if ((mp->sequence)&& (mp->rank==posPoint->secondBest[suit].rank)) weight=suitWeightDelta+39; else weight=suitWeightDelta+20+rRank; /* Encourage playing cards that previously caused search cutoff or was stored as the best move in a transposition table entry match. */ if ((localVar[thrId].bestMove[depth].suit==suit)&& (localVar[thrId].bestMove[depth].rank==mp->rank)) weight+=123/*122*//*112*//*73*/; else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) weight+=24/*20*//*17*//*14*/; } else { /* Discourage suit if RHO has winning or second best card. Exception: RHO has singleton. */ if ((posPoint->winner[suit].hand==rho[q])|| (posPoint->secondBest[suit].hand==rho[q])) { if (suitCountRH!=1) suitWeightDelta-=7; } /* Try suit if LHO has winning card and partner second best. Exception: partner has singleton. */ else if ((posPoint->winner[suit].hand==lho[q])&& (posPoint->secondBest[suit].hand==partner[q])) { /* This case was suggested by Jol Bradmetz. */ if (posPoint->length[partner[q]][suit]!=1) suitWeightDelta+=31/*34*//*37*//*32*//*20*/; } /* Encourage playing the suit if the hand together with partner have both the 2nd highest and the 3rd highest cards such that the side of the hand has the highest card in the next round playing this suit. */ if ((posPoint->secondBest[suit].hand==partner[first])&&(partner[first]==thirdBestHand)) suitWeightDelta+=22/*10*/; else if(((posPoint->secondBest[suit].hand==first)&&(partner[first]==thirdBestHand)&& (posPoint->length[partner[first]][suit]>1))||((posPoint->secondBest[suit].hand==partner[first])&& (first==thirdBestHand)&&(posPoint->length[partner[first]][suit]>1))) suitWeightDelta+=24/*10*/; /* Higher weight if LHO or RHO has the highest (winning) card as a singleton. */ if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first])) ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first]))) weight=suitWeightDelta+25/*23*//*22*/+rRank; else if (posPoint->winner[suit].hand==first) { weight=suitWeightDelta-20/*24*//*27*//*12*//*10*/+rRank; } /* Encourage playing second highest rank if hand also has third highest rank. */ else if ((mp->sequence)&& (mp->rank==posPoint->secondBest[suit].rank)) weight=suitWeightDelta+44/*42*/; else if (mp->sequence) weight=suitWeightDelta+31/*32*/-rRank; else weight=suitWeightDelta+12+rRank; /* Encourage playing cards that previously caused search cutoff or was stored as the best move in a transposition table entry match. */ if ((localVar[thrId].bestMove[depth].suit==suit)&& (localVar[thrId].bestMove[depth].rank==mp->rank)) weight+=47/*45*//*39*//*38*/; else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) weight+=13/*15*//*16*//*19*//*14*/; } break; case 1: leadSuit=posPoint->move[depth+1].suit; if (leadSuit==suit) { if (bitMapRank[mp->rank]> (bitMapRank[posPoint->move[depth+1].rank] | posPoint->rankInSuit[partner[first]][suit])) winMove=TRUE; else if (posPoint->rankInSuit[rho[first]][suit]> (bitMapRank[posPoint->move[depth+1].rank] | posPoint->rankInSuit[partner[first]][suit])) winMove=TRUE; } else { /* Side with highest rank in leadSuit wins */ if (posPoint->rankInSuit[rho[first]][leadSuit] > (posPoint->rankInSuit[partner[first]][leadSuit] | bitMapRank[posPoint->move[depth+1].rank])) winMove=TRUE; } if (winMove) { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; suitAdd=(suitCount<<6)/(23/*20*//*21*//*24*//*30*//*35*/); if (posPoint->secondBest[suit].hand==q) { /* Discourage suit discard if 2nd highest card becomes singleton. */ if (suitCount==2) suitAdd-=3; } /* Discourage suit discard of highest card. */ else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) suitAdd-=3; /*Encourage discard of low cards in long suits. */ weight=/*60*/-(mp->rank)+suitAdd; } else { weight=80+rRank; } } else { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; suitAdd=(suitCount<<6)/33; /* Discourage suit discard if 2nd highest card becomes singleton. */ if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) suitAdd-=7; /* Discourage suit discard of highest card. */ else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) suitAdd-=10; /*Encourage discard of low cards in long suits. */ weight=-(mp->rank)+suitAdd; } else { /* If lowest rank for either partner to leading hand or rho is higher than played card for lho, lho should play as low card as possible */ kk=posPoint->rankInSuit[partner[first]][leadSuit]; ll=posPoint->rankInSuit[rho[first]][leadSuit]; k=kk & (-kk); l=ll & (-ll); /* Only least significant 1 bit of bit map ranks for partner and RHO. */ if ((k > bitMapRank[mp->rank])||(l > bitMapRank[mp->rank])) weight=-3+rRank; else if (mp->rank > posPoint->move[depth+1].rank) { if (mp->sequence) { weight=/*0*/10+rRank; } else { weight=13-(mp->rank); /*weight=-5+rRank;*/ } } else { weight=-15+rRank; } } } break; case 2: leadSuit=posPoint->move[depth+2].suit; if (WinningMoveNT(mp, &(posPoint->move[depth+1]),thrId)) { if (bitMapRank[mp->rank] > posPoint->rankInSuit[rho[first]][suit]) winMove=TRUE; } else if (posPoint->high[depth+1]==first) { if (posPoint->rankInSuit[rho[first]][leadSuit] < bitMapRank[posPoint->move[depth+2].rank]) winMove=TRUE; } if (winMove) { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; suitAdd=(suitCount<<6)/(17/*27*//*30*//*35*/); /* Discourage suit discard if 2nd highest card becomes singleton. */ if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) suitAdd-=(6/*2*//*5*/); weight=-(mp->rank)+suitAdd; } else { weight=60+rRank; } } else { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; suitAdd=(suitCount<<6)/(24/*26*//*29*//*35*/); if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) suitAdd-=(4/*5*/); /* Discourage suit discard of highest card. */ else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) suitAdd-=(4/*5*/); weight=-(mp->rank)+suitAdd; } else { k=posPoint->rankInSuit[rho[first]][suit]; if ((k & (-k)) > bitMapRank[mp->rank]) weight=-(mp->rank); else if (WinningMoveNT(mp, &(posPoint->move[depth+1]), thrId)) { if ((mp->rank==posPoint->secondBest[leadSuit].rank)&& (mp->sequence)) weight=25; else if (mp->sequence) weight=20-(mp->rank); else weight=10-(mp->rank); } else weight=-10-(mp->rank); } } break; case 3: if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; suitAdd=(suitCount<<6)/(27/*35*/); if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) suitAdd-=(6/*5*/); else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) suitAdd-=(8/*9*//*8*//*5*/); weight=30-(mp->rank)+suitAdd; } else if ((posPoint->high[depth+1])==(lho[first])) { /* If the current winning move is given by the partner */ weight=30-(mp->rank); } else if (WinningMoveNT(mp, &(posPoint->move[depth+1]),thrId)) /* If present move is superior to current winning move and the current winning move is not given by the partner */ weight=30-(mp->rank); else { /* If present move is not superior to current winning move and the current winning move is not given by the partner */ weight=14-(mp->rank); } } return weight; } int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, unsigned short notVoidInSuit, int trump, int thrId) { int weight=0, k, l, kk, ll, suit, suitAdd=0, leadSuit; int suitWeightDelta, first, q, rRank, thirdBestHand; int suitBonus=0; int winMove=FALSE; /* If winMove is true, current move can win the current trick. */ unsigned short suitCount, suitCountLH, suitCountRH, aggr; int countLH, countRH; first=posPoint->first[depth]; q=handId(first, posPoint->handRelFirst); suit=mp->suit; aggr=0; for (k=0; k<=3; k++) aggr|=posPoint->rankInSuit[k][suit]; rRank=localVar[thrId].rel[aggr].relRank[mp->rank][suit]; switch (posPoint->handRelFirst) { case 0: thirdBestHand=localVar[thrId].rel[aggr].absRank[3][suit].hand; suitCount=posPoint->length[q][suit]; suitCountLH=posPoint->length[lho[q]][suit]; suitCountRH=posPoint->length[rho[q]][suit]; /* Discourage suit if LHO or RHO can ruff. */ if ((suit!=trump) && (((posPoint->rankInSuit[lho[q]][suit]==0) && (posPoint->rankInSuit[lho[q]][trump]!=0)) || ((posPoint->rankInSuit[rho[q]][suit]==0) && (posPoint->rankInSuit[rho[q]][trump]!=0)))) suitBonus=-17/*20*//*-10*/; /* Encourage suit if partner can ruff. */ if ((suit!=trump)&&(posPoint->length[partner[q]][suit]==0)&& (posPoint->length[partner[q]][trump]>0)&&(suitCountRH>0)) suitBonus+=26/*28*/; /* Discourage suit if RHO has high card. */ if ((posPoint->winner[suit].hand==rho[q])|| (posPoint->secondBest[suit].hand==rho[q])) { if (suitCountRH!=1) suitBonus-=11/*12*//*13*//*18*/; } /* Try suit if LHO has winning card and partner second best. Exception: partner has singleton. */ else if ((posPoint->winner[suit].hand==lho[q])&& (posPoint->secondBest[suit].hand==partner[q])) { /* This case was suggested by Jol Bradmetz. */ if (posPoint->length[partner[q]][suit]!=1) suitBonus+=30/*28*//*22*/; } /* Encourage play of suit where partner wins and returns the suit for a ruff. */ if ((suit!=trump)&&(suitCount==1)&& (posPoint->length[q][trump]>0)&& (posPoint->length[partner[q]][suit]>1)&& (posPoint->winner[suit].hand==partner[q])) suitBonus+=23/*24*//*19*//*16*/; if (suitCountLH!=0) countLH=(suitCountLH<<2); else countLH=depth+4; if (suitCountRH!=0) countRH=(suitCountRH<<2); else countRH=depth+4; /* Discourage a suit selection where the search tree appears larger than for the altenative suits: the search is estimated to be small when the added number of alternative cards to play for the opponents is small. */ suitWeightDelta=suitBonus- ((countLH+countRH)<<5)/(12/*15*/); if (posPoint->winner[suit].rank==mp->rank) { if ((suit!=trump)) { if ((posPoint->length[partner[first]][suit]!=0)|| (posPoint->length[partner[first]][trump]==0)) { if (((posPoint->length[lho[first]][suit]!=0)|| (posPoint->length[lho[first]][trump]==0))&& ((posPoint->length[rho[first]][suit]!=0)|| (posPoint->length[rho[first]][trump]==0))) winMove=TRUE; } else if (((posPoint->length[lho[first]][suit]!=0)|| (posPoint->rankInSuit[partner[first]][trump]> posPoint->rankInSuit[lho[first]][trump]))&& ((posPoint->length[rho[first]][suit]!=0)|| (posPoint->rankInSuit[partner[first]][trump]> posPoint->rankInSuit[rho[first]][trump]))) winMove=TRUE; } else winMove=TRUE; } else if (posPoint->rankInSuit[partner[first]][suit] > (posPoint->rankInSuit[lho[first]][suit] | posPoint->rankInSuit[rho[first]][suit])) { if (suit!=trump) { if (((posPoint->length[lho[first]][suit]!=0)|| (posPoint->length[lho[first]][trump]==0))&& ((posPoint->length[rho[first]][suit]!=0)|| (posPoint->length[rho[first]][trump]==0))) winMove=TRUE; } else winMove=TRUE; } else if (suit!=trump) { if ((posPoint->length[partner[first]][suit]==0)&& (posPoint->length[partner[first]][trump]!=0)) { if ((posPoint->length[lho[first]][suit]==0)&& (posPoint->length[lho[first]][trump]!=0)&& (posPoint->length[rho[first]][suit]==0)&& (posPoint->length[rho[first]][trump]!=0)) { if (posPoint->rankInSuit[partner[first]][trump]> (posPoint->rankInSuit[lho[first]][trump] | posPoint->rankInSuit[rho[first]][trump])) winMove=TRUE; } else if ((posPoint->length[lho[first]][suit]==0)&& (posPoint->length[lho[first]][trump]!=0)) { if (posPoint->rankInSuit[partner[first]][trump] > posPoint->rankInSuit[lho[first]][trump]) winMove=TRUE; } else if ((posPoint->length[rho[first]][suit]==0)&& (posPoint->length[rho[first]][trump]!=0)) { if (posPoint->rankInSuit[partner[first]][trump] > posPoint->rankInSuit[rho[first]][trump]) winMove=TRUE; } else winMove=TRUE; } } if (winMove) { /* Encourage ruffing LHO or RHO singleton, highest card. */ if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first])) ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first]))) weight=suitWeightDelta+39+rRank; /* Lead hand has the highest card. */ else if (posPoint->winner[suit].hand==first) { /* Also, partner has second highest card. */ if (posPoint->secondBest[suit].hand==partner[first]) weight=suitWeightDelta+46+rRank; else if (posPoint->winner[suit].rank==mp->rank) /* If the current card to play is the highest card. */ weight=suitWeightDelta+31; else weight=suitWeightDelta-2+rRank; } else if (posPoint->winner[suit].hand==partner[first]) { /* If partner has highest card */ if (posPoint->secondBest[suit].hand==first) weight=suitWeightDelta+35/*35*//*46*//*50*/+rRank; else weight=suitWeightDelta+24/*35*/+rRank; } /* Encourage playing second highest rank if hand also has third highest rank. */ else if ((mp->sequence)&& (mp->rank==posPoint->secondBest[suit].rank)) weight=suitWeightDelta+41; else if (mp->sequence) weight=suitWeightDelta+17+rRank; else weight=suitWeightDelta+11+rRank; /* Encourage playing cards that previously caused search cutoff or was stored as the best move in a transposition table entry match. */ if ((localVar[thrId].bestMove[depth].suit==suit)&& (localVar[thrId].bestMove[depth].rank==mp->rank)) weight+=53/*50*//*52*/; else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) weight+=14/*15*//*12*//*11*/; } else { /* Encourage playing the suit if the hand together with partner have both the 2nd highest and the 3rd highest cards such that the side of the hand has the highest card in the next round playing this suit. */ if ((posPoint->secondBest[suit].hand==partner[first])&&(partner[first]==thirdBestHand)) suitWeightDelta+=20/*22*/; else if(((posPoint->secondBest[suit].hand==first)&&(partner[first]==thirdBestHand)&& (posPoint->length[partner[first]][suit]>1))|| ((posPoint->secondBest[suit].hand==partner[first])&& (first==thirdBestHand)&&(posPoint->length[partner[first]][suit]>1))) suitWeightDelta+=20/*24*/; /* Higher weight if LHO or RHO has the highest (winning) card as a singleton. */ if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first])) ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first]))) weight=suitWeightDelta+rRank-2; else if (posPoint->winner[suit].hand==first) { if (posPoint->secondBest[suit].hand==partner[first]) /* Opponents win by ruffing */ weight=suitWeightDelta+33+rRank; else if (posPoint->winner[suit].rank==mp->rank) /* Opponents win by ruffing */ weight=suitWeightDelta+36; else weight=suitWeightDelta-17+rRank; } else if (posPoint->winner[suit].hand==partner[first]) { /* Opponents win by ruffing */ weight=suitWeightDelta+33+rRank; } /* Encourage playing second highest rank if hand also has third highest rank. */ else if ((mp->sequence)&& (mp->rank==posPoint->secondBest[suit].rank)) weight=suitWeightDelta+31; else weight=suitWeightDelta+13-(mp->rank); /* Encourage playing cards that previously caused search cutoff or was stored as the best move in a transposition table entry match. */ if ((localVar[thrId].bestMove[depth].suit==suit)&& (localVar[thrId].bestMove[depth].rank==mp->rank)) weight+=17; else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) weight+=(3/*4*//*10*//*9*/); } break; case 1: leadSuit=posPoint->move[depth+1].suit; if (leadSuit==suit) { if (bitMapRank[mp->rank]> (bitMapRank[posPoint->move[depth+1].rank] | posPoint->rankInSuit[partner[first]][suit])) { if (suit!=trump) { if ((posPoint->length[partner[first]][suit]!=0)|| (posPoint->length[partner[first]][trump]==0)) winMove=TRUE; else if ((posPoint->length[rho[first]][suit]==0) &&(posPoint->length[rho[first]][trump]!=0) &&(posPoint->rankInSuit[rho[first]][trump]> posPoint->rankInSuit[partner[first]][trump])) winMove=TRUE; } else winMove=TRUE; } else if (posPoint->rankInSuit[rho[first]][suit]> (bitMapRank[posPoint->move[depth+1].rank] | posPoint->rankInSuit[partner[first]][suit])) { if (suit!=trump) { if ((posPoint->length[partner[first]][suit]!=0)|| (posPoint->length[partner[first]][trump]==0)) winMove=TRUE; } else winMove=TRUE; } else if (bitMapRank[posPoint->move[depth+1].rank] > (posPoint->rankInSuit[rho[first]][suit] | posPoint->rankInSuit[partner[first]][suit] | bitMapRank[mp->rank])) { if (suit!=trump) { if ((posPoint->length[rho[first]][suit]==0)&& (posPoint->length[rho[first]][trump]!=0)) { if ((posPoint->length[partner[first]][suit]!=0)|| (posPoint->length[partner[first]][trump]==0)) winMove=TRUE; else if (posPoint->rankInSuit[rho[first]][trump] > posPoint->rankInSuit[partner[first]][trump]) winMove=TRUE; } } } else { /* winnerHand is partner to first */ if (suit!=trump) { if ((posPoint->length[rho[first]][suit]==0)&& (posPoint->length[rho[first]][trump]!=0)) winMove=TRUE; } } } else { /* Leading suit differs from suit played by LHO */ if (suit==trump) { if (posPoint->length[partner[first]][leadSuit]!=0) winMove=TRUE; else if (bitMapRank[mp->rank]> posPoint->rankInSuit[partner[first]][trump]) winMove=TRUE; else if ((posPoint->length[rho[first]][leadSuit]==0) &&(posPoint->length[rho[first]][trump]!=0)&& (posPoint->rankInSuit[rho[first]][trump] > posPoint->rankInSuit[partner[first]][trump])) winMove=TRUE; } else if (leadSuit!=trump) { /* Neither suit nor leadSuit is trump */ if (posPoint->length[partner[first]][leadSuit]!=0) { if (posPoint->rankInSuit[rho[first]][leadSuit] > (posPoint->rankInSuit[partner[first]][leadSuit] | bitMapRank[posPoint->move[depth+1].rank])) winMove=TRUE; else if ((posPoint->length[rho[first]][leadSuit]==0) &&(posPoint->length[rho[first]][trump]!=0)) winMove=TRUE; } /* Partner to leading hand is void in leading suit */ else if ((posPoint->length[rho[first]][leadSuit]==0) &&(posPoint->rankInSuit[rho[first]][trump]> posPoint->rankInSuit[partner[first]][trump])) winMove=TRUE; else if ((posPoint->length[partner[first]][trump]==0) &&(posPoint->rankInSuit[rho[first]][leadSuit] > bitMapRank[posPoint->move[depth+1].rank])) winMove=TRUE; } else { /* Either no trumps or leadSuit is trump, side with highest rank in leadSuit wins */ if (posPoint->rankInSuit[rho[first]][leadSuit] > (posPoint->rankInSuit[partner[first]][leadSuit] | bitMapRank[posPoint->move[depth+1].rank])) winMove=TRUE; } } kk=posPoint->rankInSuit[partner[first]][leadSuit]; ll=posPoint->rankInSuit[rho[first]][leadSuit]; k=kk & (-kk); l=ll & (-ll); /* Only least significant 1 bit of bit map ranks for partner and RHO. */ if (winMove) { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; suitAdd=(suitCount<<6)/(43/*36*/); /* Discourage suit discard if 2nd highest card becomes singleton. */ if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) suitAdd-=2; if (suit==trump) weight=25/*23*/-(mp->rank)+suitAdd; else weight=60-(mp->rank)+suitAdd; /* Better discard than ruff since rho wins anyway */ } else if (k > bitMapRank[mp->rank]) weight=40/*41*/+rRank; /* If lowest card for partner to leading hand is higher than lho played card, playing as low as possible will give the cheapest win */ else if ((ll > bitMapRank[posPoint->move[depth+1].rank])&& (posPoint->rankInSuit[first][leadSuit] > ll)) weight=37/*40*/+rRank; /* If rho has a card in the leading suit that is higher than the trick leading card but lower than the highest rank of the leading hand, then lho playing the lowest card will be the cheapest win */ else if (mp->rank > posPoint->move[depth+1].rank) { if (bitMapRank[mp->rank] < ll) weight=75-(mp->rank); /* If played card is lower than any of the cards of rho, it will be the cheapest win */ else if (bitMapRank[mp->rank] > kk) weight=70-(mp->rank); /* If played card is higher than any cards at partner of the leading hand, rho can play low, under the condition that he has a lower card than lho played */ else { if (mp->sequence) weight=62/*63*//*60*/-(mp->rank); else weight=48/*45*/-(mp->rank); } } else if (posPoint->length[rho[first]][leadSuit]>0) { if (mp->sequence) weight=47/*50*/-(mp->rank); /* Playing a card in a sequence may promote a winner */ /* Insensistive */ else weight=45-(mp->rank); } else weight=43/*45*/-(mp->rank); } else { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; suitAdd=(suitCount<<6)/(33/*36*/); /* Discourage suit discard if 2nd highest card becomes singleton. */ if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) suitAdd-=(4/*2*/); if (suit==trump) { weight=16/*15*/-(mp->rank)+suitAdd; /* Ruffing is preferred, makes the trick costly for the opponents */ } else weight=-6-(mp->rank)+suitAdd; } else if ((k > bitMapRank[mp->rank])|| (l > bitMapRank[mp->rank])) weight=-7/*-9*/+rRank; /* If lowest rank for either partner to leading hand or rho is higher than played card for lho, lho should play as low card as possible */ else if (mp->rank > posPoint->move[depth+1].rank) { if (mp->sequence) weight=19/*19*/-(mp->rank); else weight=10-(mp->rank); } else weight=-17+rRank; } break; case 2: leadSuit=posPoint->move[depth+2].suit; if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId)) { if (suit==leadSuit) { if (leadSuit!=trump) { if (((posPoint->length[rho[first]][suit]!=0)|| (posPoint->length[rho[first]][trump]==0))&& (bitMapRank[mp->rank] > posPoint->rankInSuit[rho[first]][suit])) winMove=TRUE; } else if (bitMapRank[mp->rank] > posPoint->rankInSuit[rho[first]][suit]) winMove=TRUE; } else { /* Suit is trump */ if (posPoint->length[rho[first]][leadSuit]==0) { if (bitMapRank[mp->rank] > posPoint->rankInSuit[rho[first]][trump]) winMove=TRUE; } else winMove=TRUE; } } else if (posPoint->high[depth+1]==first) { if (posPoint->length[rho[first]][leadSuit]!=0) { if (posPoint->rankInSuit[rho[first]][leadSuit] < bitMapRank[posPoint->move[depth+2].rank]) winMove=TRUE; } else if (leadSuit==trump) winMove=TRUE; else if ((leadSuit!=trump) && (posPoint->length[rho[first]][trump]==0)) winMove=TRUE; } if (winMove) { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; suitAdd=(suitCount<<6)/(48/*36*/); /* Discourage suit discard if 2nd highest card becomes singleton. */ if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) suitAdd-=(3/*2*/); if (posPoint->high[depth+1]==first) { if (suit==trump) weight=30-(mp->rank)+suitAdd; /* Ruffs partner's winner */ else weight=60-(mp->rank)+suitAdd; } else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId)) /* Own hand on top by ruffing */ weight=70-(mp->rank)+suitAdd; } else weight=60-(mp->rank); } else { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; suitAdd=(suitCount<<6)/36; /* Discourage suit discard if 2nd highest card becomes singleton. */ if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) suitAdd-=(4/*2*/); if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId)) /* Own hand on top by ruffing */ weight=40-(mp->rank)+suitAdd; else if (suit==trump) /* Discard a trump but still losing */ weight=-/*33*/36+rRank+suitAdd; else weight=-(mp->rank)+suitAdd; } else { k=posPoint->rankInSuit[rho[first]][suit]; if ((k & (-k)) > bitMapRank[mp->rank]) /* If least bit map rank of RHO to lead hand is higher than bit map rank of current card move. */ weight=-(mp->rank); else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId)) { /* If current card move is highest so far. */ if (mp->rank==posPoint->secondBest[leadSuit].rank) weight=25; else if (mp->sequence) weight=21/*20*/-(mp->rank); else weight=10-(mp->rank); } else weight=-10-(mp->rank); } } break; case 3: if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; suitAdd=(suitCount<<6)/(24/*36*/); if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) suitAdd-=(2/*0*//*2*/); if ((posPoint->high[depth+1])==lho[first]) { /* If the current winning move is given by the partner */ if (suit==trump) /* Ruffing partners winner? */ weight=2/*17*/-(mp->rank)+suitAdd; else weight=25-(mp->rank)+suitAdd; } else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId)) /* Own hand ruffs */ weight=33/*27*/+rRank+suitAdd; else if (suit==trump) weight=-13+rRank; else weight=14-(mp->rank)+suitAdd; } else if ((posPoint->high[depth+1])==(lho[first])) { /* If the current winning move is given by the partner */ if (suit==trump) /* Ruffs partners winner */ weight=11+rRank; else weight=17+rRank; } else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId)) /* If present move is superior to current winning move and the current winning move is not given by the partner */ weight=22+rRank; else { /* If present move is not superior to current winning move and the current winning move is not given by the partner */ if (suit==trump) /* Ruffs but still loses */ weight=-13+rRank; else weight=1+rRank; } } return weight; } /* Shell-1 */ /* K&R page 62: */ /*void shellSort(int n, int depth) { int gap, i, j; struct moveType temp; if (n==2) { if (movePly[depth].move[0].weight>1; gap>0; gap>>=1) for (i=gap; i=0 && movePly[depth].move[j].weight< movePly[depth].move[j+gap].weight; j-=gap) { temp=movePly[depth].move[j]; movePly[depth].move[j]=movePly[depth].move[j+gap]; movePly[depth].move[j+gap]=temp; } } */ /* Shell-2 */ /*void shellSort(int n, int depth) { int i, j, increment; struct moveType temp; if (n==2) { if (movePly[depth].move[0].weight 0) { for (i=0; i < n; i++) { j = i; temp = movePly[depth].move[i]; while ((j >= increment) && (movePly[depth].move[j-increment].weight < temp.weight)) { movePly[depth].move[j] = movePly[depth].move[j - increment]; j = j - increment; } movePly[depth].move[j] = temp; } if ((increment>>1) != 0) increment>>=1; else if (increment == 1) increment = 0; else increment = 1; } } */ /* Insert-1 */ /*void InsertSort(int n, int depth, struct movePlyType *mply, int thrId) { int i, j; struct moveType a, temp; if (n==2) { if (mply->move[0].weightmove[1].weight) { temp=mply->move[0]; mply->move[0]=mply->move[1]; mply->move[1]=temp; return; } else return; } a=mply->move[0]; for (i=1; i<=n-1; i++) if (mply->move[i].weight>a.weight) { temp=a; a=mply->move[i]; mply->move[i]=temp; } mply->move[0]=a; for (i=2; i<=n-1; i++) { j=i; a=mply->move[i]; while (a.weight>mply->move[j-1].weight) { mply->move[j]=mply->move[j-1]; j--; } mply->move[j]=a; } } */ /* Insert-2 */ /*void InsertSort(int n, int depth) { int i, j; struct moveType a; if (n==2) { if (movePly[depth].move[0].weight=0)&&(movePly[depth].move[i].weight a[j - 1].weight ; --j) a[j] = a[j - 1]; a[j] = tmp; } } return; } int AdjustMoveList(int thrId) { int k, r, n, rank, suit; for (k=1; k<=13; k++) { suit=localVar[thrId].forbiddenMoves[k].suit; rank=localVar[thrId].forbiddenMoves[k].rank; for (r=0; r<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; r++) { if ((suit==localVar[thrId].movePly[localVar[thrId].iniDepth].move[r].suit)&& (rank!=0)&&(rank==localVar[thrId].movePly[localVar[thrId].iniDepth].move[r].rank)) { /* For the forbidden move r: */ for (n=r; n<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; n++) localVar[thrId].movePly[localVar[thrId].iniDepth].move[n]= localVar[thrId].movePly[localVar[thrId].iniDepth].move[n+1]; localVar[thrId].movePly[localVar[thrId].iniDepth].last--; } } } return localVar[thrId].movePly[localVar[thrId].iniDepth].last+1; } int InvBitMapRank(unsigned short bitMap) { switch (bitMap) { case 0x1000: return 14; case 0x0800: return 13; case 0x0400: return 12; case 0x0200: return 11; case 0x0100: return 10; case 0x0080: return 9; case 0x0040: return 8; case 0x0020: return 7; case 0x0010: return 6; case 0x0008: return 5; case 0x0004: return 4; case 0x0002: return 3; case 0x0001: return 2; default: return 0; } } int InvWinMask(int mask) { switch (mask) { case 0x01000000: return 1; case 0x00400000: return 2; case 0x00100000: return 3; case 0x00040000: return 4; case 0x00010000: return 5; case 0x00004000: return 6; case 0x00001000: return 7; case 0x00000400: return 8; case 0x00000100: return 9; case 0x00000040: return 10; case 0x00000010: return 11; case 0x00000004: return 12; case 0x00000001: return 13; default: return 0; } } inline int WinningMove(struct moveType * mvp1, struct moveType * mvp2, int trump, int thrId) { /* Return TRUE if move 1 wins over move 2, with the assumption that move 2 is the presently winning card of the trick */ if (mvp1->suit==mvp2->suit) { if ((mvp1->rank)>(mvp2->rank)) return TRUE; else return FALSE; } else if ((mvp1->suit)==trump) return TRUE; else return FALSE; } inline int WinningMoveNT(struct moveType * mvp1, struct moveType * mvp2, int thrId) { /* Return TRUE if move 1 wins over move 2, with the assumption that move 2 is the presently winning card of the trick */ if (mvp1->suit==mvp2->suit) { if ((mvp1->rank)>(mvp2->rank)) return TRUE; else return FALSE; } else return FALSE; } struct nodeCardsType * CheckSOP(struct pos * posPoint, struct nodeCardsType * nodep, int target, int tricks, int * result, int *value, int thrId) { /* Check SOP if it matches the current position. If match, pointer to the SOP node is returned and result is set to TRUE, otherwise pointer to SOP node is returned and result set to FALSE. */ /* 07-04-22 */ if (localVar[thrId].nodeTypeStore[0]==MAXNODE) { if (nodep->lbound==-1) { /* This bound values for this leading hand has not yet been determined */ *result=FALSE; return nodep; } else if ((posPoint->tricksMAX + nodep->lbound)>=target) { *value=TRUE; *result=TRUE; return nodep; } else if ((posPoint->tricksMAX + nodep->ubound)ubound==-1) { /* This bound values for this leading hand has not yet been determined */ *result=FALSE; return nodep; } else if ((posPoint->tricksMAX + (tricks + 1 - nodep->ubound))>=target) { *value=TRUE; *result=TRUE; return nodep; } else if ((posPoint->tricksMAX + (tricks + 1 - nodep->lbound))lbound > nodep->lbound) || (nodep->lbound==-1)) nodep->lbound=posPoint->lbound; if ((posPoint->ubound < nodep->ubound) || (nodep->ubound==-1)) nodep->ubound=posPoint->ubound; nodep->bestMoveSuit=posPoint->bestMoveSuit; nodep->bestMoveRank=posPoint->bestMoveRank; return nodep; } struct nodeCardsType * FindSOP(struct pos * posPoint, struct winCardType * nodeP, int firstHand, int target, int tricks, int * valp, int thrId) { struct nodeCardsType * sopP; struct winCardType * np; int s, res; np=nodeP; s=0; while ((np!=NULL)&&(s<4)) { if ((np->winMask & posPoint->orderSet[s])== np->orderSet) { /* Winning rank set fits position */ if (s==3) { sopP=CheckSOP(posPoint, np->first, target, tricks, &res, valp, thrId); if (res) { return sopP; } else { if (np->next!=NULL) { np=np->next; } else { np=np->prevWin; s--; if (np==NULL) return NULL; while (np->next==NULL) { np=np->prevWin; s--; if (np==NULL) /* Previous node is header node? */ return NULL; } np=np->next; } } } else if (s<4) { np=np->nextWin; s++; } } else { if (np->next!=NULL) { np=np->next; } else { np=np->prevWin; s--; if (np==NULL) return NULL; while (np->next==NULL) { np=np->prevWin; s--; if (np==NULL) /* Previous node is header node? */ return NULL; } np=np->next; } } } return NULL; } struct nodeCardsType * BuildPath(struct pos * posPoint, struct posSearchType *nodep, int * result, int thrId) { /* If result is TRUE, a new SOP has been created and BuildPath returns a pointer to it. If result is FALSE, an existing SOP is used and BuildPath returns a pointer to the SOP */ int found, suit; struct winCardType * np, * p2, /* * sp2,*/ * nprev, * fnp, *pnp; struct winCardType temp; struct nodeCardsType * sopP=0, * p/*, * sp*/; np=nodep->posSearchPoint; nprev=NULL; suit=0; /* If winning node has a card that equals the next winning card deduced from the position, then there already exists a (partial) path */ if (np==NULL) { /* There is no winning list created yet */ /* Create winning nodes */ p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; AddWinSet(thrId); p2->next=NULL; p2->nextWin=NULL; p2->prevWin=NULL; nodep->posSearchPoint=p2; p2->winMask=posPoint->winMask[suit]; p2->orderSet=posPoint->winOrderSet[suit]; p2->first=NULL; np=p2; /* Latest winning node */ suit++; while (suit<4) { p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; AddWinSet(thrId); np->nextWin=p2; p2->prevWin=np; p2->next=NULL; p2->nextWin=NULL; p2->winMask=posPoint->winMask[suit]; p2->orderSet=posPoint->winOrderSet[suit]; p2->first=NULL; np=p2; /* Latest winning node */ suit++; } p=&localVar[thrId].nodeCards[localVar[thrId].nodeSetSize]; AddNodeSet(thrId); np->first=p; *result=TRUE; return p; } else { /* Winning list exists */ while (1) { /* Find all winning nodes that correspond to current position */ found=FALSE; while (1) { /* Find node amongst alternatives */ if ((np->winMask==posPoint->winMask[suit])&& (np->orderSet==posPoint->winOrderSet[suit])) { /* Part of path found */ found=TRUE; nprev=np; break; } if (np->next!=NULL) np=np->next; else break; } if (found) { suit++; if (suit>3) { sopP=UpdateSOP(posPoint, np->first); if (np->prevWin!=NULL) { pnp=np->prevWin; fnp=pnp->nextWin; } else fnp=nodep->posSearchPoint; temp.orderSet=np->orderSet; temp.winMask=np->winMask; temp.first=np->first; temp.nextWin=np->nextWin; np->orderSet=fnp->orderSet; np->winMask=fnp->winMask; np->first=fnp->first; np->nextWin=fnp->nextWin; fnp->orderSet=temp.orderSet; fnp->winMask=temp.winMask; fnp->first=temp.first; fnp->nextWin=temp.nextWin; *result=FALSE; return sopP; } else { np=np->nextWin; /* Find next winning node */ continue; } } else break; /* Node was not found */ } /* End outer while */ /* Create additional node, coupled to existing node(s) */ p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; AddWinSet(thrId); p2->prevWin=nprev; if (nprev!=NULL) { p2->next=nprev->nextWin; nprev->nextWin=p2; } else { p2->next=nodep->posSearchPoint; nodep->posSearchPoint=p2; } p2->nextWin=NULL; p2->winMask=posPoint->winMask[suit]; p2->orderSet=posPoint->winOrderSet[suit]; p2->first=NULL; np=p2; /* Latest winning node */ suit++; /* Rest of path must be created */ while (suit<4) { p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; AddWinSet(thrId); np->nextWin=p2; p2->prevWin=np; p2->next=NULL; p2->winMask=posPoint->winMask[suit]; p2->orderSet=posPoint->winOrderSet[suit]; p2->first=NULL; p2->nextWin=NULL; np=p2; /* Latest winning node */ suit++; } /* All winning nodes in SOP have been traversed and new nodes created */ p=&localVar[thrId].nodeCards[localVar[thrId].nodeSetSize]; AddNodeSet(thrId); np->first=p; *result=TRUE; return p; } } struct posSearchType * SearchLenAndInsert(struct posSearchType * rootp, long long key, int insertNode, int *result, int thrId) { /* Search for node which matches with the suit length combination given by parameter key. If no such node is found, NULL is returned if parameter insertNode is FALSE, otherwise a new node is inserted with suitLengths set to key, the pointer to this node is returned. The algorithm used is defined in Knuth "The art of computer programming", vol.3 "Sorting and searching", 6.2.2 Algorithm T, page 424. */ struct posSearchType *np, *p, *sp; if (insertNode) sp=&localVar[thrId].posSearch[localVar[thrId].lenSetSize]; np=rootp; while (1) { if (key==np->suitLengths) { *result=TRUE; return np; } else if (key < np->suitLengths) { if (np->left!=NULL) np=np->left; else if (insertNode) { p=sp; AddLenSet(thrId); np->left=p; p->posSearchPoint=NULL; p->suitLengths=key; p->left=NULL; p->right=NULL; *result=TRUE; return p; } else { *result=FALSE; return NULL; } } else { /* key > suitLengths */ if (np->right!=NULL) np=np->right; else if (insertNode) { p=sp; AddLenSet(thrId); np->right=p; p->posSearchPoint=NULL; p->suitLengths=key; p->left=NULL; p->right=NULL; *result=TRUE; return p; } else { *result=FALSE; return NULL; } } } } void BuildSOP(struct pos * posPoint, int tricks, int firstHand, int target, int depth, int scoreFlag, int score, int thrId) { int ss, hh, res, wm; unsigned short int w; unsigned short int temp[4][4]; unsigned short int aggr[4]; struct nodeCardsType * cardsP; struct posSearchType * np; long long suitLengths; #ifdef TTDEBUG int k, mcurrent, rr; mcurrent=localVar[thrId].movePly[depth].current; #endif for (ss=0; ss<=3; ss++) { w=posPoint->winRanks[depth][ss]; if (w==0) { posPoint->winMask[ss]=0; posPoint->winOrderSet[ss]=0; posPoint->leastWin[ss]=0; for (hh=0; hh<=3; hh++) temp[hh][ss]=0; } else { w=w & (-w); /* Only lowest win */ for (hh=0; hh<=3; hh++) temp[hh][ss]=posPoint->rankInSuit[hh][ss] & (-w); aggr[ss]=0; for (hh=0; hh<=3; hh++) aggr[ss]=aggr[ss] | temp[hh][ss]; posPoint->winMask[ss]=localVar[thrId].rel[aggr[ss]].winMask[ss]; posPoint->winOrderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss]; wm=posPoint->winMask[ss]; wm=wm & (-wm); posPoint->leastWin[ss]=InvWinMask(wm); } } /* 07-04-22 */ if (scoreFlag) { if (localVar[thrId].nodeTypeStore[0]==MAXNODE) { posPoint->ubound=tricks+1; posPoint->lbound=target-posPoint->tricksMAX; } else { posPoint->ubound=tricks+1-target+posPoint->tricksMAX; posPoint->lbound=0; } } else { if (localVar[thrId].nodeTypeStore[0]==MAXNODE) { posPoint->ubound=target-posPoint->tricksMAX-1; posPoint->lbound=0; } else { posPoint->ubound=tricks+1; posPoint->lbound=tricks+1-target+posPoint->tricksMAX+1; } } suitLengths=0; for (ss=0; ss<=2; ss++) for (hh=0; hh<=3; hh++) { suitLengths<<=4; suitLengths|=posPoint->length[hh][ss]; } np=SearchLenAndInsert(localVar[thrId].rootnp[tricks][firstHand], suitLengths, TRUE, &res, thrId); cardsP=BuildPath(posPoint, np, &res, thrId); if (res) { cardsP->ubound=posPoint->ubound; cardsP->lbound=posPoint->lbound; if (((localVar[thrId].nodeTypeStore[firstHand]==MAXNODE)&&(scoreFlag))|| ((localVar[thrId].nodeTypeStore[firstHand]==MINNODE)&&(!scoreFlag))) { cardsP->bestMoveSuit=localVar[thrId].bestMove[depth].suit; cardsP->bestMoveRank=localVar[thrId].bestMove[depth].rank; } else { cardsP->bestMoveSuit=0; cardsP->bestMoveRank=0; } posPoint->bestMoveSuit=localVar[thrId].bestMove[depth].suit; posPoint->bestMoveRank=localVar[thrId].bestMove[depth].rank; for (ss=0; ss<=3; ss++) cardsP->leastWin[ss]=posPoint->leastWin[ss]; } #ifdef STAT c9[depth]++; #endif #ifdef TTDEBUG if ((res) && (ttCollect) && (!suppressTTlog)) { fprintf(localVar[thrId].fp7, "cardsP=%d\n", (int)cardsP); fprintf(localVar[thrId].fp7, "nodeSetSize=%d\n", localVar[thrId].nodeSetSize); fprintf(localVar[thrId].fp7, "ubound=%d\n", cardsP->ubound); fprintf(localVar[thrId].fp7, "lbound=%d\n", cardsP->lbound); fprintf(localVar[thrId].fp7, "target=%d\n", target); fprintf(localVar[thrId].fp7, "first=%c nextFirst=%c\n", cardHand[posPoint->first[depth]], cardHand[posPoint->first[depth-1]]); fprintf(localVar[thrId].fp7, "bestMove: suit=%c rank=%c\n", cardSuit[localVar[thrId].bestMove[depth].suit], cardRank[localVar[thrId].bestMove[depth].rank]); fprintf(localVar[thrId].fp7, "\n"); fprintf(localVar[thrId].fp7, "Last trick:\n"); fprintf(localVar[thrId].fp7, "1st hand=%c\n", cardHand[posPoint->first[depth+3]]); for (k=3; k>=0; k--) { mcurrent=localVar[thrId].movePly[depth+k+1].current; fprintf(localVar[thrId].fp7, "suit=%c rank=%c\n", cardSuit[localVar[thrId].movePly[depth+k+1].move[mcurrent].suit], cardRank[localVar[thrId].movePly[depth+k+1].move[mcurrent].rank]); } fprintf(localVar[thrId].fp7, "\n"); for (hh=0; hh<=3; hh++) { fprintf(localVar[thrId].fp7, "hand=%c\n", cardHand[hh]); for (ss=0; ss<=3; ss++) { fprintf(localVar[thrId].fp7, "suit=%c", cardSuit[ss]); for (rr=14; rr>=2; rr--) if (posPoint->rankInSuit[hh][ss] & bitMapRank[rr]) fprintf(localVar[thrId].fp7, " %c", cardRank[rr]); fprintf(localVar[thrId].fp7, "\n"); } fprintf(localVar[thrId].fp7, "\n"); } fprintf(localVar[thrId].fp7, "\n"); } #endif } int CheckDeal(struct moveType * cardp, int thrId) { int h, s, k, found; unsigned short int temp[4][4]; for (h=0; h<=3; h++) for (s=0; s<=3; s++) temp[h][s]=localVar[thrId].game.suit[h][s]; /* Check that all ranks appear only once within the same suit. */ for (s=0; s<=3; s++) for (k=2; k<=14; k++) { found=FALSE; for (h=0; h<=3; h++) { if ((temp[h][s] & bitMapRank[k])!=0) { if (found) { cardp->suit=s; cardp->rank=k; return 1; } else found=TRUE; } } } return 0; } int NextMove(struct pos *posPoint, int depth, struct movePlyType *mply, int thrId) { /* Returns TRUE if at least one move remains to be searched, otherwise FALSE is returned. */ int mcurrent; unsigned short int lw; unsigned char suit; struct moveType currMove; mcurrent=mply->current; currMove=mply->move[mcurrent]; if (localVar[thrId].lowestWin[depth][currMove.suit]==0) { /* A small card has not yet been identified for this suit. */ lw=posPoint->winRanks[depth][currMove.suit]; if (lw!=0) lw=lw & (-lw); /* LSB */ else lw=bitMapRank[15]; if (bitMapRank[currMove.rank]current <= (mply->last-1)) { mply->current++; mcurrent=mply->current; if (bitMapRank[mply->move[mcurrent].rank] >= localVar[thrId].lowestWin[depth][mply->move[mcurrent].suit]) return TRUE; } return FALSE; } else { while (mply->current <= (mply->last-1)) { mply->current++; mcurrent=mply->current; suit=mply->move[mcurrent].suit; if ((currMove.suit==suit) || (bitMapRank[mply->move[mcurrent].rank] >= localVar[thrId].lowestWin[depth][suit])) return TRUE; } return FALSE; } } else { while (mply->current<=(mply->last-1)) { mply->current++; mcurrent=mply->current; if (bitMapRank[mply->move[mcurrent].rank] >= localVar[thrId].lowestWin[depth][mply->move[mcurrent].suit]) return TRUE; } return FALSE; } } int DumpInput(int errCode, struct deal dl, int target, int solutions, int mode) { FILE *fp; int i, j, k; unsigned short ranks[4][4]; fp=fopen("dump.txt", "w"); if (fp==NULL) return -1; fprintf(fp, "Error code=%d\n", errCode); fprintf(fp, "\n"); fprintf(fp, "Deal data:\n"); if (dl.trump!=4) fprintf(fp, "trump=%c\n", cardSuit[dl.trump]); else fprintf(fp, "trump=N\n"); fprintf(fp, "first=%c\n", cardHand[dl.first]); for (k=0; k<=2; k++) if (dl.currentTrickRank[k]!=0) fprintf(fp, "index=%d currentTrickSuit=%c currentTrickRank=%c\n", k, cardSuit[dl.currentTrickSuit[k]], cardRank[dl.currentTrickRank[k]]); for (i=0; i<=3; i++) for (j=0; j<=3; j++) { fprintf(fp, "index1=%d index2=%d remainCards=%d\n", i, j, dl.remainCards[i][j]); ranks[i][j]=dl.remainCards[i][/*3-*/j]>>2; } fprintf(fp, "\n"); fprintf(fp, "target=%d\n", target); fprintf(fp, "solutions=%d\n", solutions); fprintf(fp, "mode=%d\n", mode); fprintf(fp, "\n"); PrintDeal(fp, ranks); fclose(fp); return 0; } void PrintDeal(FILE *fp, unsigned short ranks[][4]) { int i, count, ec[4], trickCount=0, s, r; for (i=0; i<=3; i++) { count=counttable[ranks[3][i]]; if (count>5) ec[i]=TRUE; else ec[i]=FALSE; trickCount=trickCount+count; } fprintf(fp, "\n"); for (s=0; s<=3; s++) { fprintf(fp, "\t%c ", cardSuit[s]); if (!ranks[0][s]) fprintf(fp, "--"); else { for (r=14; r>=2; r--) if ((ranks[0][s] & bitMapRank[r])!=0) fprintf(fp, "%c", cardRank[r]); } fprintf(fp, "\n"); } for (s=0; s<=3; s++) { fprintf(fp, "%c ", cardSuit[s]); if (!ranks[3][s]) fprintf(fp, "--"); else { for (r=14; r>=2; r--) if ((ranks[3][s] & bitMapRank[r])!=0) fprintf(fp, "%c", cardRank[r]); } if (ec[s]) fprintf(fp, "\t\%c ", cardSuit[s]); else fprintf(fp, "\t\t\%c ", cardSuit[s]); if (!ranks[1][s]) fprintf(fp, "--"); else { for (r=14; r>=2; r--) if ((ranks[1][s] & bitMapRank[r])!=0) fprintf(fp, "%c", cardRank[r]); } fprintf(fp, "\n"); } for (s=0; s<=3; s++) { fprintf(fp, "\t%c ", cardSuit[s]); if (!ranks[2][s]) fprintf(fp, "--"); else { for (r=14; r>=2; r--) if ((ranks[2][s] & bitMapRank[r])!=0) fprintf(fp, "%c", cardRank[r]); } fprintf(fp, "\n"); } fprintf(fp, "\n"); return; } void Wipe(int thrId) { int k; for (k=1; k<=localVar[thrId].wcount; k++) { if (localVar[thrId].pw[k]) free(localVar[thrId].pw[k]); localVar[thrId].pw[k]=NULL; } for (k=1; k<=localVar[thrId].ncount; k++) { if (localVar[thrId].pn[k]) free(localVar[thrId].pn[k]); localVar[thrId].pn[k]=NULL; } for (k=1; k<=localVar[thrId].lcount; k++) { if (localVar[thrId].pl[k]) free(localVar[thrId].pl[k]); localVar[thrId].pl[k]=NULL; } localVar[thrId].allocmem=localVar[thrId].summem; return; } void AddWinSet(int thrId) { if (localVar[thrId].clearTTflag) { localVar[thrId].windex++; localVar[thrId].winSetSize=localVar[thrId].windex; /*localVar[thrId].fp2=fopen("dyn.txt", "a"); fprintf(localVar[thrId].fp2, "windex=%d\n", windex); fclose(localVar[thrId].fp2);*/ localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex]; } else if (localVar[thrId].winSetSize>=localVar[thrId].winSetSizeLimit) { /* The memory chunk for the winCards structure will be exceeded. */ if ((localVar[thrId].allocmem+localVar[thrId].wmem)>localVar[thrId].maxmem) { /* Already allocated memory plus needed allocation overshot maxmem */ localVar[thrId].windex++; localVar[thrId].winSetSize=localVar[thrId].windex; /*localVar[thrId].fp2=fopen("dyn.txt", "a"); fprintf(localVar[thrId].fp2, "windex=%d\n", windex); fclose(localVar[thrId].fp2);*/ localVar[thrId].clearTTflag=TRUE; localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex]; } else { localVar[thrId].wcount++; localVar[thrId].winSetSizeLimit=WSIZE; localVar[thrId].pw[localVar[thrId].wcount] = (struct winCardType *)calloc(localVar[thrId].winSetSizeLimit+1, sizeof(struct winCardType)); if (localVar[thrId].pw[localVar[thrId].wcount]==NULL) { localVar[thrId].clearTTflag=TRUE; localVar[thrId].windex++; localVar[thrId].winSetSize=localVar[thrId].windex; localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex]; } else { localVar[thrId].allocmem+=(localVar[thrId].winSetSizeLimit+1)*sizeof(struct winCardType); localVar[thrId].winSetSize=0; localVar[thrId].winCards=localVar[thrId].pw[localVar[thrId].wcount]; } } } else localVar[thrId].winSetSize++; return; } void AddNodeSet(int thrId) { if (localVar[thrId].nodeSetSize>=localVar[thrId].nodeSetSizeLimit) { /* The memory chunk for the nodeCards structure will be exceeded. */ if ((localVar[thrId].allocmem+localVar[thrId].nmem)>localVar[thrId].maxmem) { /* Already allocated memory plus needed allocation overshot maxmem */ localVar[thrId].clearTTflag=TRUE; } else { localVar[thrId].ncount++; localVar[thrId].nodeSetSizeLimit=NSIZE; localVar[thrId].pn[localVar[thrId].ncount] = (struct nodeCardsType *)calloc(localVar[thrId].nodeSetSizeLimit+1, sizeof(struct nodeCardsType)); if (localVar[thrId].pn[localVar[thrId].ncount]==NULL) { localVar[thrId].clearTTflag=TRUE; } else { localVar[thrId].allocmem+=(localVar[thrId].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType); localVar[thrId].nodeSetSize=0; localVar[thrId].nodeCards=localVar[thrId].pn[localVar[thrId].ncount]; } } } else localVar[thrId].nodeSetSize++; return; } void AddLenSet(int thrId) { if (localVar[thrId].lenSetSize>=localVar[thrId].lenSetSizeLimit) { /* The memory chunk for the posSearchType structure will be exceeded. */ if ((localVar[thrId].allocmem+localVar[thrId].lmem)>localVar[thrId].maxmem) { /* Already allocated memory plus needed allocation overshot maxmem */ localVar[thrId].clearTTflag=TRUE; } else { localVar[thrId].lcount++; localVar[thrId].lenSetSizeLimit=LSIZE; localVar[thrId].pl[localVar[thrId].lcount] = (struct posSearchType *)calloc(localVar[thrId].lenSetSizeLimit+1, sizeof(struct posSearchType)); if (localVar[thrId].pl[localVar[thrId].lcount]==NULL) { localVar[thrId].clearTTflag=TRUE; } else { localVar[thrId].allocmem+=(localVar[thrId].lenSetSizeLimit+1)*sizeof(struct posSearchType); localVar[thrId].lenSetSize=0; localVar[thrId].posSearch=localVar[thrId].pl[localVar[thrId].lcount]; } } } else localVar[thrId].lenSetSize++; return; } #ifdef TTDEBUG void ReceiveTTstore(struct pos *posPoint, struct nodeCardsType * cardsP, int target, int depth, int thrId) { int tricksLeft, hh, ss, rr; /* Stores current position information and TT position value in table ttStore with current entry lastTTStore. Also stores corresponding information in log rectt.txt. */ tricksLeft=0; for (hh=0; hh<=3; hh++) for (ss=0; ss<=3; ss++) tricksLeft+=posPoint->length[hh][ss]; tricksLeft=tricksLeft/4; ttStore[lastTTstore].tricksLeft=tricksLeft; ttStore[lastTTstore].cardsP=cardsP; ttStore[lastTTstore].first=posPoint->first[depth]; if ((localVar[thrId].handToPlay==posPoint->first[depth])|| (localVar[thrId].handToPlay==partner[posPoint->first[depth]])) { ttStore[lastTTstore].target=target-posPoint->tricksMAX; ttStore[lastTTstore].ubound=cardsP->ubound; ttStore[lastTTstore].lbound=cardsP->lbound; } else { ttStore[lastTTstore].target=tricksLeft- target+posPoint->tricksMAX+1; } for (hh=0; hh<=3; hh++) for (ss=0; ss<=3; ss++) ttStore[lastTTstore].suit[hh][ss]= posPoint->rankInSuit[hh][ss]; localVar[thrId].fp11=fopen("rectt.txt", "a"); if (lastTTstoretricksMAX); fprintf(localVar[thrId].fp11, "leftTricks=%d\n", ttStore[lastTTstore].tricksLeft); fprintf(localVar[thrId].fp11, "cardsP=%d\n", ttStore[lastTTstore].cardsP); fprintf(localVar[thrId].fp11, "ubound=%d\n", ttStore[lastTTstore].ubound); fprintf(localVar[thrId].fp11, "lbound=%d\n", ttStore[lastTTstore].lbound); fprintf(localVar[thrId].fp11, "first=%c\n", cardHand[ttStore[lastTTstore].first]); fprintf(localVar[thrId].fp11, "target=%d\n", ttStore[lastTTstore].target); fprintf(localVar[thrId].fp11, "\n"); for (hh=0; hh<=3; hh++) { fprintf(localVar[thrId].fp11, "hand=%c\n", cardHand[hh]); for (ss=0; ss<=3; ss++) { fprintf(localVar[thrId].fp11, "suit=%c", cardSuit[ss]); for (rr=14; rr>=2; rr--) if (ttStore[lastTTstore].suit[hh][ss] & bitMapRank[rr]) fprintf(localVar[thrId].fp11, " %c", cardRank[rr]); fprintf(localVar[thrId].fp11, "\n"); } fprintf(localVar[thrId].fp11, "\n"); } } fclose(localVar[thrId].fp11); lastTTstore++; } #endif #if defined(_WIN32) HANDLE solveAllEvents[MAXNOOFTHREADS]; struct paramType param; LONG volatile threadIndex; LONG volatile current; const long chunk = 4; DWORD CALLBACK SolveChunkDDtable (void *) { struct futureTricks fut[MAXNOOFBOARDS]; int thid; long j; thid=InterlockedIncrement(&threadIndex); while ((j=InterlockedExchangeAdd(¤t, chunk))deals[j+k], param.bop->target[j+k], param.bop->solutions[j+k], param.bop->mode[j+k], &fut[j+k], thid); if (res==1) { param.solvedp->solvedBoard[j+k]=fut[j+k]; param.error=0; } else { param.error=res; } } } if (SetEvent(solveAllEvents[thid])==0) { /*int errCode=GetLastError();*/ return 0; } return 1; } int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp) { int k/*, errCode*/; DWORD res; DWORD solveAllWaitResult; current=0; threadIndex=-1; if (bop->noOfBoards > MAXNOOFBOARDS) return -101; for (k=0; knoOfBoards; for (k=0; ksolvedBoard[k].cards=0; for (k=0; knoOfBoards=0; for (k=0; ksolvedBoard[k].cards!=0) solvedp->noOfBoards++; } if (param.error==0) return 1; else return param.error; } DWORD CALLBACK SolveChunk (void *) { struct futureTricks fut[MAXNOOFBOARDS]; int thid; long j; thid=InterlockedIncrement(&threadIndex); while ((j=(InterlockedIncrement(¤t)-1))deals[j], param.bop->target[j], param.bop->solutions[j], param.bop->mode[j], &fut[j], thid); if (res==1) { param.solvedp->solvedBoard[j]=fut[j]; param.error=0; } else { param.error=res; } } if (SetEvent(solveAllEvents[thid])==0) { /*int errCode=GetLastError();*/ return 0; } return 1; } int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp) { int k/*, errCode*/; DWORD res; DWORD solveAllWaitResult; current=0; threadIndex=-1; if (bop->noOfBoards > MAXNOOFBOARDS) return -201; for (k=0; knoOfBoards; for (k=0; ksolvedBoard[k].cards=0; for (k=0; knoOfBoards=0; for (k=0; ksolvedBoard[k].cards!=0) solvedp->noOfBoards++; } if (param.error==0) return 1; else return param.error; } #else int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp) { int k, i, res, chunk, fail; struct futureTricks fut[MAXNOOFBOARDS]; chunk=4; fail=1; if (bop->noOfBoards > MAXNOOFBOARDS) return -101; for (i=0; isolvedBoard[i].cards=0; #ifdef _OPENMP omp_set_num_threads(noOfCores); /* Added after suggestion by Dirk Willecke. */ #endif #pragma omp parallel shared(bop, solvedp, chunk, fail) private(k) { #pragma omp for schedule(dynamic, chunk) for (k=0; knoOfBoards; k++) { res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k], bop->mode[k], &fut[k], #ifdef _OPENMP omp_get_thread_num() #else 0 #endif ); if (res==1) { solvedp->solvedBoard[k]=fut[k]; } else fail=res; } } if (fail!=1) return fail; solvedp->noOfBoards=0; for (i=0; isolvedBoard[i].cards!=0) solvedp->noOfBoards++; } return 1; } int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp) { int k, i, res, chunk, fail; struct futureTricks fut[MAXNOOFBOARDS]; chunk=1; fail=1; if (bop->noOfBoards > MAXNOOFBOARDS) return -101; for (i=0; isolvedBoard[i].cards=0; #ifdef _OPENMP omp_set_num_threads(noOfCores); /* Added after suggestion by Dirk Willecke. */ #endif #pragma omp parallel shared(bop, solvedp, chunk, fail) private(k) { #pragma omp for schedule(dynamic, chunk) for (k=0; knoOfBoards; k++) { res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k], bop->mode[k], &fut[k], #ifdef _OPENMP omp_get_thread_num() #else 0 #endif ); if (res==1) { solvedp->solvedBoard[k]=fut[k]; } else fail=res; } } if (fail!=1) return fail; solvedp->noOfBoards=0; for (i=0; isolvedBoard[i].cards!=0) solvedp->noOfBoards++; } return 1; } #endif int STDCALL CalcDDtable(struct ddTableDeal tableDeal, struct ddTableResults * tablep) { int h, s, k, ind, tr, first, res; struct deal dl; struct boards bo; struct solvedBoards solved; for (h=0; h<=3; h++) for (s=0; s<=3; s++) dl.remainCards[h][s]=tableDeal.cards[h][s]; for (k=0; k<=2; k++) { dl.currentTrickRank[k]=0; dl.currentTrickSuit[k]=0; } ind=0; bo.noOfBoards=20; for (tr=4; tr>=0; tr--) for (first=0; first<=3; first++) { dl.first=first; dl.trump=tr; bo.deals[ind]=dl; bo.target[ind]=-1; bo.solutions[ind]=1; bo.mode[ind]=1; ind++; } res=SolveAllBoards4(&bo, &solved); if (res==1) { for (ind=0; ind<20; ind++) { tablep->resTable[bo.deals[ind].trump][rho[bo.deals[ind].first]]= 13-solved.solvedBoard[ind].score[0]; } return 1; } return res; } int STDCALL CalcAllTables(struct ddTableDeals *dealsp, int mode, int trumpFilter[5], struct ddTablesRes *resp, struct allParResults *presp) { /* mode = 0: par calculation, vulnerability None mode = 1: par calculation, vulnerability All mode = 2: par calculation, vulnerability NS mode = 3: par calculation, vulnerability EW mode = -1: no par calculation */ int h, s, k, m, ind, tr, first, res, rs, lastIndex=0, lastBoardIndex[MAXNOOFBOARDS>>2], okey=FALSE, count=0; struct boards bo; struct solvedBoards solved; int Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable); for (k=0; k<5; k++) { if (!trumpFilter[k]) { okey=TRUE; count++; } } if (!okey) return -201; switch (count) { case 1: if (dealsp->noOfTables > 50) return 202; break; case 2: if (dealsp->noOfTables > 25) return 202; break; case 3: if (dealsp->noOfTables > 16) return 202; break; case 4: if (dealsp->noOfTables > 12) return 202; break; case 5: if (dealsp->noOfTables > 10) return 202; break; } ind=0; resp->noOfBoards=0; for (m=0; mnoOfTables; m++) { for (tr=4; tr>=0; tr--) { if (!trumpFilter[tr]) { for (first=0; first<=3; first++) { for (h=0; h<=3; h++) for (s=0; s<=3; s++) bo.deals[ind].remainCards[h][s]=dealsp->deals[m].cards[h][s]; bo.deals[ind].first=first; bo.deals[ind].trump=tr; for (k=0; k<=2; k++) { bo.deals[ind].currentTrickRank[k]=0; bo.deals[ind].currentTrickSuit[k]=0; } bo.target[ind]=-1; bo.solutions[ind]=1; bo.mode[ind]=1; lastIndex=ind; lastBoardIndex[m]=ind; ind++; } } } } bo.noOfBoards=lastIndex+1; res=SolveAllBoards4(&bo, &solved); if (res==1) { resp->noOfBoards+=solved.noOfBoards; for (ind=0; ind<=lastIndex; ind++) { for (k=0; k<=lastIndex; k++) { if (ind<=lastBoardIndex[k]) { resp->results[k].resTable[bo.deals[ind].trump][rho[bo.deals[ind].first]]= 13-solved.solvedBoard[ind].score[0]; break; } } } if ((mode > -1) && (mode < 4)) { /* Calculate par */ for (k=0; knoOfTables; k++) { rs=Par(&(resp->results[k]), &(presp->presults[k]), mode); /* vulnerable 0: None 1: Both 2: NS 3: EW */ if (rs!=1) return rs; } } return 1; } return res; } int STDCALL CalcAllTablesPBN(struct ddTableDealsPBN *dealsp, int mode, int trumpFilter[5], struct ddTablesRes *resp, struct allParResults *presp) { int res, k; struct ddTableDeals dls; int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]); for (k=0; knoOfTables; k++) if (ConvertFromPBN(dealsp->deals[k].cards, dls.deals[k].cards)!=1) return -99; dls.noOfTables=dealsp->noOfTables; res=CalcAllTables(&dls, mode, trumpFilter, resp, presp); return res; } int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]) { int bp=0, first, card, hand, handRelFirst, suitInHand, h, s; int IsCard(char cardChar); for (h=0; h<=3; h++) for (s=0; s<=3; s++) remainCards[h][s]=0; while (((dealBuff[bp]!='W')&&(dealBuff[bp]!='N')&& (dealBuff[bp]!='E')&&(dealBuff[bp]!='S')&& (dealBuff[bp]!='w')&&(dealBuff[bp]!='n')&& (dealBuff[bp]!='e')&&(dealBuff[bp]!='s'))&&(bp<3)) bp++; if (bp>=3) return 0; if ((dealBuff[bp]=='N')||(dealBuff[bp]=='n')) first=0; else if ((dealBuff[bp]=='E')||(dealBuff[bp]=='e')) first=1; else if ((dealBuff[bp]=='S')||(dealBuff[bp]=='s')) first=2; else first=3; bp++; bp++; handRelFirst=0; suitInHand=0; while ((bp<80)&&(dealBuff[bp]!='\0')) { card=IsCard(dealBuff[bp]); if (card) { switch (first) { case 0: hand=handRelFirst; break; case 1: if (handRelFirst==0) hand=1; else if (handRelFirst==3) hand=0; else hand=handRelFirst+1; break; case 2: if (handRelFirst==0) hand=2; else if (handRelFirst==1) hand=3; else hand=handRelFirst-2; break; default: if (handRelFirst==0) hand=3; else hand=handRelFirst-1; } remainCards[hand][suitInHand]|=(bitMapRank[card]<<2); } else if (dealBuff[bp]=='.') suitInHand++; else if (dealBuff[bp]==' ') { handRelFirst++; suitInHand=0; } bp++; } return 1; } int IsCard(char cardChar) { switch (cardChar) { case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; case 'T': return 10; case 'J': return 11; case 'Q': return 12; case 'K': return 13; case 'A': return 14; case 't': return 10; case 'j': return 11; case 'q': return 12; case 'k': return 13; case 'a': return 14; default: return 0; } } #ifdef PBN int STDCALL SolveBoardPBN(struct dealPBN dlpbn, int target, int solutions, int mode, struct futureTricks *futp, int thrId) { int res, k; struct deal dl; int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]); if (ConvertFromPBN(dlpbn.remainCards, dl.remainCards)!=1) return -99; for (k=0; k<=2; k++) { dl.currentTrickRank[k]=dlpbn.currentTrickRank[k]; dl.currentTrickSuit[k]=dlpbn.currentTrickSuit[k]; } dl.first=dlpbn.first; dl.trump=dlpbn.trump; res=SolveBoard(dl, target, solutions, mode, futp, thrId); return res; } int STDCALL CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, struct ddTableResults * tablep) { struct ddTableDeal tableDeal; int res; if (ConvertFromPBN(tableDealPBN.cards, tableDeal.cards)!=1) return -99; res=CalcDDtable(tableDeal, tablep); return res; } #endif #ifdef PBN_PLUS int STDCALL SolveAllBoards(struct boardsPBN *bop, struct solvedBoards *solvedp) { struct boards bo; int k, i, res; bo.noOfBoards=bop->noOfBoards; for (k=0; knoOfBoards; k++) { bo.mode[k]=bop->mode[k]; bo.solutions[k]=bop->solutions[k]; bo.target[k]=bop->target[k]; bo.deals[k].first=bop->deals[k].first; bo.deals[k].trump=bop->deals[k].trump; for (i=0; i<=2; i++) { bo.deals[k].currentTrickSuit[i]=bop->deals[k].currentTrickSuit[i]; bo.deals[k].currentTrickRank[i]=bop->deals[k].currentTrickRank[i]; } if (ConvertFromPBN(bop->deals[k].remainCards, bo.deals[k].remainCards)!=1) return -99; } res=SolveAllBoards1(&bo, solvedp); return res; } #endif #ifdef PBN_PLUS int STDCALL CalcParPBN(struct ddTableDealPBN tableDealPBN, struct ddTableResults * tablep, int vulnerable, struct parResults *presp) { int res; struct ddTableDeal tableDeal; int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]); int STDCALL CalcPar(struct ddTableDeal tableDeal, int vulnerable, struct ddTableResults * tablep, struct parResults *presp); if (ConvertFromPBN(tableDealPBN.cards, tableDeal.cards)!=1) return -99; res=CalcPar(tableDeal, vulnerable, tablep, presp); return res; } int STDCALL CalcPar(struct ddTableDeal tableDeal, int vulnerable, struct ddTableResults * tablep, struct parResults *presp) { int res; int Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable); res=CalcDDtable(tableDeal, tablep); if (res!=1) return res; res=Par(tablep, presp, vulnerable); return res; } #endif int Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable) { /* vulnerable 0: None 1: Both 2: NS 3: EW */ /* The code for calculation of par score / contracts is based upon the perl code written by Matthew Kidd ACBLmerge. He has kindly given me permission to include a C++ adaptation in DDS. */ /* The Par function computes the par result and contracts. */ int denom_conv[5]={4, 0, 1, 2, 3}; /* Preallocate for efficiency. These hold result from last direction (N-S or E-W) examined. */ int i, j, k, m, isvul; int current_side, both_sides_once_flag, denom_max, max_lower; int new_score_flag, sc1, sc2; int prev_par_denom=0, prev_par_tricks=0; int ut, t1, t2, tt, score, dr, ke, tu, tu_max, t3, t4, n; struct par_suits_type par_suits[5]; char contr_sep[2]={',','\0'}; char temp[8], buff[4]; int par_denom[2] = {-1, -1}; /* 0-4 = NT,S,H,D,C */ int par_tricks[2] = {6, 6}; /* Initial "contract" beats 0 NT */ int par_score[2] = {0, 0}; int par_sacut[2] = {0, 0}; /* Undertricks for sacrifice (0 if not sac) */ int rawscore(int denom, int tricks, int isvul); void IniSidesString(int dr, int i, int t1, int t2, char stri[]); int CalcMultiContracts(int max_lower, int tricks); /* Find best par result for N-S (i==0) or E-W (i==1). These will nearly always be the same, but when we have a "hot" situation they will not be. */ for (i=0; i<=1; i++) { /* Start with the with the offensive side (current_side = 0) and alternate between sides seeking the to improve the result for the current side.*/ current_side=0; both_sides_once_flag=0; while (1) { /* Find best contract for current side that beats current contract. Choose highest contract if results are equal. */ k=(i+current_side) % 2; isvul=((vulnerable==1)||(k ? (vulnerable==3) : (vulnerable==2))); new_score_flag=0; prev_par_denom=par_denom[i]; prev_par_tricks=par_tricks[i]; /* Calculate tricks and score values and store them for each denomination in structure par_suits[5]. */ for (j=0; j<=4; j++) { t1 = k ? tablep->resTable[denom_conv[j]][1] : tablep->resTable[denom_conv[j]][0]; t2 = k ? tablep->resTable[denom_conv[j]][3] : tablep->resTable[denom_conv[j]][2]; tt = Max(t1, t2); /* tt is the maximum number of tricks current side can take in denomination.*/ par_suits[j].suit=j; par_suits[j].tricks=tt; if ((tt > par_tricks[i]) || ((tt == par_tricks[i]) && (j < par_denom[i]))) par_suits[j].score=rawscore(j, tt, isvul); else par_suits[j].score=rawscore(-1, prev_par_tricks - tt, isvul); } /* Sort the items in the par_suits structure with decreasing order of the values on the scores. */ for (int s = 1; s < 5; s++) { struct par_suits_type tmp = par_suits[s]; int r = s; for (; r && tmp.score > par_suits[r - 1].score ; --r) par_suits[r] = par_suits[r - 1]; par_suits[r] = tmp; } /* Do the iteration as before but now in the order of the sorted denominations. */ for (m=0; m<=4; m++) { j=par_suits[m].suit; tt=par_suits[m].tricks; if ((tt > par_tricks[i]) || ((tt == par_tricks[i]) && (j < par_denom[i]))) { /* Can bid higher and make contract.*/ score=rawscore(j, tt, isvul); } else { /* Bidding higher in this denomination will not beat previous denomination and may be a sacrifice. */ ut=prev_par_tricks - tt; if (j >= prev_par_denom) { /* Sacrifices higher than 7N are not permitted (but long ago the official rules did not prohibit bidding higher than 7N!) */ if (prev_par_tricks == 13) continue; /* It will be necessary to bid one level higher, resulting in one more undertrick. */ ut++; } /* Not a sacrifice (due to par_tricks > prev_par_tricks) */ if (ut <= 0) continue; /* Compute sacrifice.*/ score=rawscore(-1, ut, isvul); } if (current_side == 1) score=-score; if (((current_side == 0)&&(score > par_score[i])) || ((current_side == 1)&&(score < par_score[i]))) { new_score_flag = 1; par_score[i] = score; par_denom[i] = j; if (((current_side == 0)&&(score > 0)) || ((current_side == 1)&&(score < 0))) { /* New par score from a making contract. Can immediately update since score at same level in higher ranking suit is always >= score in lower ranking suit and better than any sacrifice. */ par_tricks[i] = tt; par_sacut[i] = 0; } else { par_tricks[i] = tt + ut; par_sacut[i] = ut; } } } if (!new_score_flag && both_sides_once_flag) break; both_sides_once_flag = 1; current_side = 1 - current_side; } } presp->parScore[0][0]='N'; presp->parScore[0][1]='S'; presp->parScore[0][2]=' '; presp->parScore[0][3]='\0'; presp->parScore[1][0]='E'; presp->parScore[1][1]='W'; presp->parScore[1][2]=' '; presp->parScore[1][3]='\0'; /*itoa(par_score[0], temp, 10);*/ sprintf(temp, "%d", par_score[0]); strcat(presp->parScore[0], temp); /*itoa(par_score[1], temp, 10);*/ sprintf(temp, "%d", par_score[1]); strcat(presp->parScore[1], temp); for (i=0; i<=1; i++) { presp->parContractsString[0][0]='N'; presp->parContractsString[0][1]='S'; presp->parContractsString[0][2]=':'; presp->parContractsString[0][3]='\0'; presp->parContractsString[1][0]='E'; presp->parContractsString[1][1]='W'; presp->parContractsString[1][2]=':'; presp->parContractsString[1][3]='\0'; } if (par_score[0] == 0) { /* Neither side can make anything.*/ return 1; } for (i=0; i<=1; i++) { if ( par_sacut[i] > 0 ) { dr = (par_score[i] > 0) ? 0 : 1; for (j=par_denom[i]; j<=4; j++) { t1 = ((dr+i) % 2 ) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1]; t2 = ((dr+i) % 2 ) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3]; tt = (t1 > t2) ? t1 : t2; tu_max=0; for (m=0; m<=4; m++) { t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1]; t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3]; tu = (t3 > t4) ? t3 : t4; if (tu > tu_max) { tu_max=tu; denom_max=m; } } if (((par_tricks[i] - par_sacut[i]) != tt)||((par_denom[i] < denom_max)&&(j > denom_max))) continue; /* Continue if the par denomination is lower than the denomination of the opponent's highest trick number and the current denomination is larger than the denomination of the opponent's highest trick number. */ IniSidesString(dr, i, t1, t2, buff); if (presp->parContractsString[i][3]!='\0') strcat(presp->parContractsString[i], contr_sep); strcat(presp->parContractsString[i], buff); /*itoa(par_tricks[i]-6, temp, 10);*/ sprintf(temp, "%d", par_tricks[i]-6); buff[0]=cardSuit[denom_conv[j]]; buff[1]='x'; buff[2]='\0'; strcat(temp, buff); strcat(presp->parContractsString[i], temp); stat_contr[0]++; } } else { /* Par contract is a makeable contract.*/ dr = (par_score[i] < 0) ? 0 : 1; /* If spades or diamonds, lower major / minor may also be a par contract.*/ ke = (par_denom[i] == 1 || par_denom[i] == 3) ? 1 : 0; for (j=par_denom[i]; j<=par_denom[i]+ke; j++) { t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1]; t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3]; tt = (t1 > t2) ? t1 : t2; if (tt < par_tricks[i]) { continue; } IniSidesString(dr, i, t1, t2, buff); tu_max=0; for (m=0; m<=4; m++) { t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1]; t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3]; tu = (t3 > t4) ? t3 : t4; if (tu > tu_max) { tu_max=tu; denom_max=m; /* Lowest denomination if several denominations have max tricks. */ } } if (presp->parContractsString[i][3]!='\0') strcat(presp->parContractsString[i], contr_sep); strcat(presp->parContractsString[i], buff); if (denom_max < par_denom[i]) max_lower = par_tricks[i] - tu_max - 1; else max_lower = par_tricks[i] - tu_max; /* max_lower is the maximal contract lowering, otherwise opponent contract is higher. It is already known that par_score is high enough to make opponent sacrifices futile. To find the actual contract lowering allowed, it must be checked that the lowered contract still gets the score bonus points that is present in par score.*/ sc2 = rawscore(par_denom[i], par_tricks[i], isvul); /* Score for making the tentative lower par contract. */ while (max_lower > 0) { if (denom_max < par_denom[i]) sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max, isvul); else sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max + 1, isvul); /* Score for undertricks needed to beat the tentative lower par contract.*/ if (sc2 < sc1) break; else max_lower--; /* Tentative lower par contract must be 1 trick higher, since the cost for the sacrifice is too small. */ } switch (par_denom[i]) { case 0: k = 0; break; case 1: case 2: k = 1; break; case 3: case 4: k = 2; } max_lower = Min(max_low[k][par_tricks[i]-6], max_lower); n = CalcMultiContracts(max_lower, par_tricks[i]); /*itoa(n, temp, 10);*/ sprintf(temp, "%d", n); buff[0]=cardSuit[denom_conv[j]]; buff[1]='\0'; strcat(temp, buff); strcat(presp->parContractsString[i], temp); stat_contr[1]++; } /* Deal with special case of 3N/5m (+400/600) */ if ((par_denom[i] == 0) && (par_tricks[i] == 9)) { for (j=3; j<=4; j++) { t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1]; t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3]; tt = (t1 > t2) ? t1 : t2; if (tt != 11) { continue; } IniSidesString(dr, i, t1, t2, buff); if (presp->parContractsString[i][3]!='\0') strcat(presp->parContractsString[i], contr_sep); strcat(presp->parContractsString[i], buff); /*itoa(5, temp, 10);*/ sprintf(temp, "%d", 5); buff[0]=cardSuit[denom_conv[j]]; buff[1]='\0'; strcat(temp, buff); strcat(presp->parContractsString[i], temp); stat_contr[2]++; } } /* Deal with special case of 2S/2H (+110) which may have 3C and 3D as additional par contract(s).*/ if ((par_denom[i] <=2) && (par_denom[i] != 0) && (par_tricks[i] == 8)) { /* Check if 3C and 3D make.*/ for (j=3; j<=4; j++) { t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1]; t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3]; tt = (t1 > t2) ? t1 : t2; if (tt != 9) { continue; } IniSidesString(dr, i, t1, t2, buff); tu_max=0; for (m=0; m<=4; m++) { t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1]; t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3]; tu = (t3 > t4) ? t3 : t4; if (tu > tu_max) { tu_max=tu; denom_max=m; } } if (presp->parContractsString[i][3]!='\0') strcat(presp->parContractsString[i], contr_sep); strcat(presp->parContractsString[i], buff); if (denom_max < j) max_lower = 9 - tu_max - 1; else max_lower = 9 - tu_max; /* max_lower is the maximal contract lowering, otherwise opponent contract is higher. It is already known that par_score is high enough to make opponent sacrifices futile. To find the actual contract lowering allowed, it must be checked that the lowered contract still gets the score bonus points that is present in par score.*/ sc2 = rawscore(par_denom[i], par_tricks[i], isvul); /* Score for making the tentative lower par contract. */ while (max_lower > 0) { if (denom_max < j) sc1 = -rawscore(-1, 9/*par_tricks[i] + 1*/ - max_lower - tu_max, isvul); else sc1 = -rawscore(-1, 9 - max_lower - tu_max + 1, isvul); /* Score for undertricks needed to beat the tentative lower par contract.*/ if (sc2 < sc1) break; else max_lower--; /* Tentative lower par contract must be 1 trick higher, since the cost for the sacrifice is too small. */ } switch (par_denom[i]) { case 0: k = 0; break; case 1: case 2: k = 1; break; case 3: case 4: k = 2; } max_lower = Min(max_low[k][3], max_lower); n = CalcMultiContracts(max_lower, 9); /*itoa(n, temp, 10);*/ sprintf(temp, "%d", n); buff[0]=cardSuit[denom_conv[j]]; buff[1]='\0'; strcat(temp, buff); strcat(presp->parContractsString[i], temp); stat_contr[3]++; } } /* Deal with special case 1NT (+90) which may have 2C or 2D as additonal par contracts(s). */ if ((par_denom[i] == 0) && (par_tricks[i] == 7)) { for (j=3; j<=4; j++) { t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1]; t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3]; tt = (t1 > t2) ? t1 : t2; if (tt != 8) { continue; } IniSidesString(dr, i, t1, t2, buff); tu_max=0; /*for (m=4; m>=0; m--) {*/ for (m=0; m<=4; m++) { t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1]; t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3]; tu = (t3 > t4) ? t3 : t4; if (tu > tu_max) { tu_max=tu; denom_max=m; } } if (presp->parContractsString[i][3]!='\0') strcat(presp->parContractsString[i], contr_sep); strcat(presp->parContractsString[i], buff); if (denom_max < j) max_lower = 8 - tu_max - 1; else max_lower = 8 - tu_max; /* max_lower is the maximal contract lowering, otherwise opponent contract is higher. It is already known that par_score is high enough to make opponent sacrifices futile. To find the actual contract lowering allowed, it must be checked that the lowered contract still gets the score bonus points that is present in par score.*/ sc2 = rawscore(par_denom[i], par_tricks[i], isvul); /* Score for making the tentative lower par contract. */ while (max_lower > 0) { if (denom_max < j) sc1 = -rawscore(-1, 8 - max_lower - tu_max, isvul); else sc1 = -rawscore(-1, 8 - max_lower - tu_max + 1, isvul); /* Score for undertricks needed to beat the tentative lower par contract.*/ if (sc2 < sc1) break; else max_lower--; /* Tentative lower par contract must be 1 trick higher, since the cost for the sacrifice is too small. */ } switch (par_denom[i]) { case 0: k = 0; break; case 1: case 2: k = 1; break; case 3: case 4: k = 2; } max_lower = Min(max_low[k][3], max_lower); n = CalcMultiContracts(max_lower, 8); /*itoa(n, temp, 10);*/ sprintf(temp, "%d", n); buff[0]=cardSuit[denom_conv[j]]; buff[1]='\0'; strcat(temp, buff); strcat(presp->parContractsString[i], temp); stat_contr[4]++; } } } } return 1; } int rawscore(int denom, int tricks, int isvul) { int game_bonus, level, score; /* Computes score for undoubled contract or a doubled contract with for a given number of undertricks. These are the only possibilities for a par contract (aside from a passed out hand). denom - 0 = NT, 1 = Spades, 2 = Hearts, 3 = Diamonds, 4 = Clubs (same order as results from double dummy solver); -1 undertricks tricks - For making contracts (7-13); otherwise, number of undertricks. isvul - True if vulnerable */ if (denom==-1) { if (isvul) return -300 * tricks + 100; if (tricks<=3) return -200 * tricks + 100; return -300 * tricks + 400; } else { level=tricks-6; game_bonus=0; if (denom==0) { score=10 + 30 * level; if (level>=3) game_bonus=1; } else if ((denom==1)||(denom==2)) { score=30 * level; if (level>=4) game_bonus=1; } else { score=20 * level; if (level>=5) game_bonus=1; } if (game_bonus) { score+= (isvul ? 500 : 300); } else score+=50; if (level==6) { score+= (isvul ? 750 : 500); } else if (level==7) { score+= (isvul ? 1500 : 1000); } } return score; } void IniSidesString(int dr, int i, int t1, int t2, char stri[]) { if ((dr+i) % 2 ) { if (t1==t2) { stri[0]='N'; stri[1]='S'; stri[2]=' '; stri[3]='\0'; } else if (t1 > t2) { stri[0]='N'; stri[1]=' '; stri[2]='\0'; } else { stri[0]='S'; stri[1]=' '; stri[2]='\0'; } } else { if (t1==t2) { stri[0]='E'; stri[1]='W'; stri[2]=' '; stri[3]='\0'; } else if (t1 > t2) { stri[0]='E'; stri[1]=' '; stri[2]='\0'; } else { stri[0]='W'; stri[1]=' '; stri[2]='\0'; } } return; } int CalcMultiContracts(int max_lower, int tricks) { int n; switch (tricks-6) { case 5: if (max_lower==3) {n = 2345;} else if (max_lower==2) {n = 345;} else if (max_lower==1) {n = 45;} else {n = 5;} break; case 4: if (max_lower==3) {n = 1234;} else if (max_lower==2) {n = 234;} else if (max_lower==1) {n = 34;} else {n = 4;} break; case 3: if (max_lower==2) {n = 123;} else if (max_lower==1) {n = 23;} else {n = 3;} break; case 2: if (max_lower==1) {n = 12;} else {n = 2;} break; default: n = tricks-6; } return n; } dds-2.4.2+ddd105/mode2.txt0000664000401600040160000000405110621316247013061 0ustar cbecbe Usage of the SolveBoard parameter option mode=2 ----------------------------------------------- When the score of a deal is to be calculated for different hands leading the first trick, the mode parameter in SolveBoard can be used to speed up the calculation. The score of the first alternative leading hand is obtained by setting mode=1. The parameter target can be set to -1 or to a defined target value. The parameter solutions can be set to either 1, 2 or 3. The following calls to SolveBoard for the other alternative leading hands can all have parameter mode set to 2. When mode is set to 2, the transposition table contents is not cleared before making the alpha-beta search for the obtaining the score, giving a faster search. A function calculating the score for all possible leading hands using mode=2 must be part of the application using DDS. Below is source code for such function using C, assuming target is set to -1 and solutions set to 1. Setting target to a specific value and/or setting solutions different to 1 can be done using a similar solution. Source code example using C --------------------------- void SolveCamps(int est) { /* est is estimated target. dl is an externally declared struct of type deal. fut is an externally declared structure of type futureTricks. SolveCamps needs to called for each of the suits of the deal, i.e. for each dl.suit. score[h] is an externally declared integer array which will contain the score for each leading hand. totalNodes[h] is an externally declared counter array of type int that adds up the searched nodes for each leading hand. */ int h, k; for (h=0; h<=3; h++) totalNodes[h]=0; for (h=0; h<=3; h++) { dl.first=h; if (h==0) k=SolveBoard(dl, -1, 1, 1, &fut); else k=SolveBoard(dl, -1, 1, 2, &fut); score[h]=fut.score[0]; totalNodes[h]=totalNodes[h]+fut.nodes; } } dds-2.4.2+ddd105/DDS_alg_descr-revE4.txt0000664000401600040160000012214411361026142015451 0ustar cbecbeBo Haglund Rev. E4, 2010-04-09 Search Algorithms for a Bridge Double Dummy Solver This description is intended for anyone interested in the inner workings of a bridge double dummy solver (DDS). It describes my solver implemented in the Win32 environment as a DLL. DDS algorithm descriptions already exist, see reference list at the end. However, to my knowledge, no document exists that gives an in depth description of all algorithms covered in this document. 1.The basic search algorithm The search is based on the zero window search [Pearl 1980]. Pseudo code for its application on DD solver search is given. Cards searched are described as ”moves” in contrast to cards that are really played. int Search(posPoint, target, depth) { if (depth==0) { tricks=Evaluate; if (tricks >= target) value=TRUE; else value=FALSE; return value; } else { GenerateMoves; if (player_side_to_move) { value=FALSE; moveExists=TRUE; while (moveExists) { Make; value=Search(posPoint, target, depth-1); Undo; if (value==TRUE) goto searchExit; /* Cutoff, current move recorded as ”best move” */ moveExists=NextMove; } } /* Opponents to move */ else { value=TRUE; moveExists=TRUE; while (moveExists) { Make; value=Search(posPoint, target, depth-1); Undo; if (value==FALSE) goto searchExit; /* Cutoff, current move recorded as ”best move” */ moveExists=NextMove; } } } searchExit: return value; } The Search parameters are: posPoint - a pointer to a structure containing state information for the position (deal) to be searched, e.g. leading hand, hand-to-play, cards yet to play etc. target - the number of tricks the player must take. depth - the current search depth. Search returns TRUE if the target is reached, otherwise FALSE. When Search is called, depth is set to the number of cards left to play minus 4. GenerateMoves generates a list of alternative moves (=cards) that can be played in the initial position whose state data is pointed to by posPoint. For cards that are equivalent (e.g. AK) only the card with highest rank is generated. Card equivalence is reanalyzed after each trick. E.g. if the hand-to-play has AQ in a suit where K was played in a previous trick, then A and Q become equivalents. If the side of the player has the move, Search tries to find a move that meets the target, i.e that evaluates to TRUE. If such a move is found, search returns TRUE, and saves the move as ”best”. If the other side has the move, Search tries to find a move that defies meeting the target, i.e. that evaluates to FALSE. If such a move is found, search returns FALSE, and saves the move as ”best”. Each move in the generated move list is handled by first calling Make, which removes the card from the position state information. Search is then recursively called with a position state that now has excluded the played card, depth has been decremented by one. For each new recursive call to Search, a card is removed from the position state information and depth is decremented. This goes on until depth equals 0 in which case only one trick remains. The outcome of this trick is calculated by Evaluate. If the total number of tricks won by the side of the player then reaches target, Search returns TRUE, otherwise FALSE. This result propagates upwards as Search returns for each level, Undo is called which reinstalls the searched card on this level. Finally, Search returns for the top level. This basic search algorithm is not powerful enough to terminate the search of a typical 52 cards deal in a reasonable time. To accomplish this, a number of search algorithm enhancements are required, which will be described in the following chapters. The described search algorithm only tells if a predefined target can be reached. It does not tell how many tricks that the side of the player can get. This is accomplished by repeated calls to Search: g = guessed number of tricks for side of the player iniDepth = number of cards to play minus 4 upperbound = 13; lowerbound = 0; do { if (g==lowerbound) tricks=g+1; else tricks=g; if ((Search(posPoint, tricks, iniDepth)==FALSE) { upperbound=tricks-1; g=upperbound; } else { lowerbound=tricks; g=lowerbound; } } while (lowerbound < upperbound); g=maximum tricks to be won by side of player. 2.Overview of the search algorithms used in the DD solver The additional functions in the pseudo code for supporting the search speed enhancements are given in italics. int Search(posPoint, target, depth) { if (no_move_yet_in_trick) { TargetTooLowOrHigh; if (target_already_obtained) return TRUE; else if (target_can_no_longer_be_obtained) return FALSE; QuickTricks; LaterTricks; if (cutoff_for_player_side) return TRUE; else if (cutoff_for_opponent_side) return FALSE; RetrieveTTresult; if (transposition_table_entry_match) { if (target_reached) return TRUE; else return FALSE; } } if (depth==0) { evalRes=Evaluate; if (evalRes.tricks >= target) value=TRUE; else value=FALSE; return value; } else { GenerateMoves; MoveOrdering; CheckMovesForCutoff; /* For pseudo-code, see chapter 6 */ if (player_side_to_move) { value=FALSE; moveExists=TRUE; while (moveExists) { Make; value=Search(posPoint, target, depth-1); Undo; if (value==TRUE) { MergeMoveData; goto searchExit; /* Cutoff, current move recorded as ”best move” */ } MergeAllMovesData; moveExists=NextMove; } } /* Opponents to move */ else { value=TRUE; moveExists=TRUE; while (moveExists) { Make; value=Search(posPoint, target, depth-1); Undo; if (value==FALSE) { MergeMoveData; goto searchExit; /* Cutoff, current move recorded as ”best move” */ } MergeAllMovesData; moveExists=NextMove; } } } searchExit: AddNewTTentry; return value; } TargetTooLowOrHigh checks the target value against the number of tricks currently won by side of the player and against number of tricks left to play. It is executed at the beginning of each trick, before any card has been played. If number of currently won tricks by player’s side equals or exceeds target, Search returns TRUE. If number of currently won tricks by player’s side plus tricks left to play is less than target Search returns FALSE. Since possible winning cards for the remaining tricks are irrelevant, no winning cards are backed up at cutoff termination. TargetTooLowOrHigh search enhancement is described e.g. in [Chang]. QuickTricks determines if the side to move can take one or more sure tricks. E.g. if the hand to move has an Ace in an NT contract, at least one sure trick can be taken. It is executed at the beginning of each trick, before any card has been played. A simple quick trick is also executed after the leading card of the trick is played. Assuming that the sure tricks are won by the side to move, then the conditions for search cutoff in TargetTooLowOrHigh are again tested to produce further search cutoffs. The detailed conditions for determination of sure tricks are described in Chapter 3. When quicktricks win by rank, they are backed up at cutoff termination. The idea of QuickTricks is described e.g. in [Chang]. LaterTricks determines if the opponents of the side to move can take one or more tricks at their turn or later in the play. It is also executed at the beginning of each trick and uses similar criteria for search cutoff as Quicktricks. When quicktricks win by rank, they are backed up at cutoff termination. For a detailed description, see Chapter 4. RetrieveTTresult scans the set of positions in the transposition table to see if there is a match against the current position. It is executed at the beginning of each trick, before any card has been played. After detection of a transposition table entry match, the winning ranks necessary in the remaining cards are backed up. For details, see Chapter 7. Evaluate returns evalResult which updates the position state information. evalResult contains: evalResult.tricks, the number of tricks won by the side of the player, and evalResult.winRank which includes the card in the last trick that won by rank. E.g. if the last trick includes the spades A, Q, 9 and 3, evalResult.winRank returns spade A. But if the last trick was won without a win by rank as for spade 5 (leading and winning card), heart A, heart Q, heart 5, no winning rank is returned. Keeping record of cards that win by ranks and subsequently using this information to ignore ranks for other cards is discussed in the Partition Search concept invented by Matthew Ginsberg and described in his paper [Ginsberg]. MoveOrdering. The alternative cards created by MoveGenerate are sorted, with the cards most likely to terminate the search fastest being sorted first in the move list.The allocation of card weights are described in detail in Chapter 5. CheckMovesForCutoff checks if any of the moves just generated will lead to a position that can be found in the transposition table. If so, an immediate Search return can be done, saving unnecessary search effort. This is further described in Chapter 6. To my knowledge this is not described anywhere for usage in a DDS. It is described in [Plaat et al.] and named Enhanced Transposition Cutoffs. At move search cutoff, MergeMoveData collects the union of the backed up accumulated winning ranks and the rank of the made move, assuming it did win by rank. The state data of the position is updated with the collected information. MergeAllMovesData collects the union of the backed up accumulated winning ranks, the previous accumulated winning ranks of the alternative moves generated on this depth, and the rank of the made move, assuming it did win by rank. When all alternative moves have been searched without a cutoff, the state data of the position is updated with the collected information. The information from MergeMoveData and MergeAllMovesData is later stored in the transposition table and determines which ranks that are essential when RetrieveTTresult scans the set of positions in the transposition table. A match of ranks with the current position is only needed for winning ranks. See Chapter 7. AddNewTTentry adds the evaluated position as a new entry in the transposition table. See Chapter 7. NextMove filters out all ”small” cards except one per hand/suit combination. A ”small” card is a backed up card that is shown to never win by rank. The rest of the ”small” card moves for the hand/suit combination are never searched, leading to a smaller search tree. This search enhancement was suggested by Hans Kuijf [Kuijf]. 3.The Quick Tricks cutoff algorithm The number of tricks that can immediately be taken by the side to play the leading card of the trick consists of: a)The number of tricks that can be taken by the hand-to-play, and b)The number of tricks that can be taken by the partner of the hand-to-play At return by QuickTricks, the position state information is updated with the winning ranks found. Of course, in order to add b), there must be an entry from the hand-to-play to the partner’s hand. For each ”s” (suit) the following is calculated: If the hand-to-play is the only hand having cards in s, and the opponents have no trumps (when s is not trumps), the number of quick tricks for s is the suit length of the hand-to-play. If the opponents have no trumps, a check is made to see if quick tricks equal to the maximum of the trumps length for leading hand and the partner causes a search cutoff. If the hand-to-play has a card in a suit where the partner has a winning rank, and partner is the only hand having cards in s: The number of quick tricks for s is the suit length of partner. Else: If the winning rank is in hand-to-play, and the opponents cannot ruff, the number of quick tricks is incremented by one. Further, if the second best rank is also in hand-to-play, and the opponents cannot still ruff, the quick tricks is again incremented by one. Else: If the winning rank is in partner and partner has winning rank as entry, the same applies for the partner as for the hand-to-play described above. If it is a trump contract, the first suit to be investigated is the trump suit. Then if there are trump suit quick tricks for the side to play, those are cashed and quick tricks incremented accordingly. When the other suits are investigated for quick tricks, only the remaining opponent trump cards need to be considered. The quick tricks are then summarized from each suit, and the total calculated. A simple Quick Tricks algorithm is also executed after the leading card of the trick has been played: A quick trick is gained either if the hand-to-play or the partner can win the current trick with the card having the highest rank of the suit played, or if hand-to-play or the partner can win the trick by ruffing. The idea to also execute Quick Tricks after the leading card has been played was given by Hans Kuijf [Kuijf]. 4.The Later Tricks cutoff algorithm Check for search cutoff if the opponents to the trick leading hand have at least a sure trick later. If not trump contract: 1)The opponents have at least a sure trick if for all suits where the trick leading hand has a card, the side of the leading hand does not have the highest rank. More than one sure trick can be taken by the opponents if they possess the winning rank for more than one suit, or 2)Assume that all suits where the side of the trick leading hand has the winning rank give maximum possible number of tricks, i.e. that the sure trick number is the sum of the maximum lengths of these suits. If this still cannot cause a cutoff for the trick leading side, allocate one sure trick for the opponents side. If trump contract: Quick tricks for the opponents of the leading hand are added when the opponents have one or more winning trumps. This idea was given by Pedja Stanojevic [Stanojevic]. 1) If the opponent side have all the trumps, the number of sure tricks is the maximum suit length length, or 2) If the opponent side has the highest trump, they have 1 sure trick. If they also have the second highest trump, they have 2 sure tricks, or 3) If the opponent side has the second highest trump plus at least one trump more behind the hand with the highest trump, the opponent side has 1 sure trick. 5.The Move Ordering algorithm The weight of a card in the move list is affected by the suit and the rank of the card and by the other cards in the same trick. The weights of the cards in the move list are used to sort them, with the cards having the highest weight being sorted first in the list. If the hand-to-play is trick leading hand or void in the suit played by leading hand, the card with the highest weight for each present suit will get a high additional bonus weight. After list resorting, those cards will occupy the first positions in the move list. Two "best moves" are maintained for each searched depth, one for an alpha-beta cutoff and one at a Transposition Table entry match. At an alpha-beta cutoff, the move causing the cutoff overwrites the present "best move" for the current depth. When a Transposition Table entry is created, the current best move is stored in that entry if: The target is met and the leading hand belongs to the player’s side, or target is not met and the leading hand belongs to the other side. Otherwise the best move is not stored in the Transposition Table entry. At a Transposition Table entry match, its stored best move will be best move for the current search depth. By ”card move” in the following pseudo code is meant the card by the hand-to-play that is getting a weight in the move list. The ”card rank” is a value in the range 2-14, corresponding to the card ranks 2 to the Ace. For the determination of the weight, it is calculated whether or not the current card move is a card that wins the current trick for the side of the hand-to-play, assuming that both sides play their optimum cards. If the hand-to-play is void in the trick lead suit, the suit selected for the discard gets the following bonus: suitAdd = ((suit length) * 64)/36; If the suit length is 2, and the hand-to-play has the next highest rank of the suit, the bonus (suitAdd) is subtracted by 2. Hand-to-play is trick leading hand The contribution of the suit to the weight: suitWeightDelta = suitBonus – ((countLH+countRH) * 32)/15 suitBonus has the initial value 0, changed if conditions below apply: If trump contract, and the suit is not trump, then there is a (negative) suitBonus change of –10 if LHO is void and LHO has trump card(s), or RHO is void and RHO has trump card(s) If RHO has either the highest rank of the suit played by hand-to-play or the next highest rank, then there is a suitBonus change of –18. If it is a trump contract, the suit is not trump, own hand has a singleton, own hand has at least one trump, partner has the highest rank in the suit and at least a suit length of 2, then there is a suitBonus change of +16. countLH = (suit length of LHO) * 4, if LHO is not void in the suit, countLH = (depth + 4), if LHO is void in the suit countRH = (suit length of RHO) * 4, if RHO is not void in the suit, countRH = (depth + 4), if RHO is void in the suit Suits are thus favoured where the opponents have as few move alternatives as possible. if (trick winning card move) { if (one of the opponents has a singleton highest rank in the suit) weight = suitWeightDelta + 40 – (rank of card move) else if (hand-to-play has highest rank in suit) { if (partner has second highest rank in suit) weight = suitWeightDelta + 50 – (rank of card move) else if (the card move is the card with highest rank in the suit) weight = suitWeightDelta + 31 else weight = suitWeightDelta + 19 – (rank of card move) } else if (partner has highest rank in suit) { if (hand-to-play has second highest rank in suit) weight = suitWeightDelta + 50 – (rank of card move) else weight = suitWeightDelta + 35 – (rank of card move) } else if (hand-to-play has second highest rank together with equivalent card(s) in suit) weight = suitWeightDelta + 40 else weight = suitWeightDelta + 30 – (rank of card move) if (the card move is ”best move” as obtained at alpha-beta cutoff) weight = weight + 52; if (the card move is ”best move” as obtained from a Transposition Table entry match) weight = weight + 11; } else { /* Not a trick winning move */ if (either LHO or RHO has singleton in suit which has highest rank) weight = suitWeightDelta + 29 – (rank of card move) else if (hand-to-play has highest rank in suit) { if (partner has second highest rank in suit) weight = suitWeightDelta + 44 – (rank of card move) else if (the card move is the card with highest rank in the suit) weight = suitWeightDelta + 25 else weight = suitWeightDelta + 13 – (rank of card move) } else if (partner has highest rank in suit) { if (hand-to-play has second highest rank in suit) weight = suitWeightDelta + 44 – (rank of card move) else weight = suitWeightDelta + 29 – (rank of card move) } else if (hand-to-play has second highest rank together with equivalent card(s) in suit) weight = suitWeightDelta + 29 else weight = suitWeightDelta + 13 – (rank of card move) if (the card move is ”best move” as obtained at alpha-beta cutoff) weight = weight + 20; if (the card move is ”best move” as obtained from a Transposition Table entry match) weight = weight + 9; } Hand-to-play is left hand opponent (LHO) to leading hand if (trick winning card move) { if (hand-to-play void in the suit played by the leading hand) { if (trump contract and trump is equal to card move suit) weight = 30 - (rank of card move) + suitAdd else weight = 60 - (rank of card move) + suitAdd } else if (lowest card for partner to leading hand is higher than LHO played card) weight = 45 - (rank of card move) else if (RHO has a card in the leading suit that is higher than the trick leading card but lower than the highest rank of the leading hand) weight = 60 - (rank of card move) else if (LHO played card is higher than card played by the leading hand) { if (played card by LHO is lower than any card for RHO in the same suit) weight = 75 - (rank of card move) else if (played card by LHO is higher than any card in the same suit for the leading hand) weight = 70 - (rank of card move) else { if (LHO move card has at least one equivalent card) { weight = 60 - (rank of card move) else weight = 45 - (rank of card move) } } else if (RHO is not void in the suit played by the leading hand) { if (LHO move card has at least one equivalent card) weight = 50 - (rank of card move) else weight = 45 - (rank of card move) } else weight = 45 - (rank of card move) } else { /* card move is not trick winning */ if (hand-to-play void in the suit played by the leading hand) { if (trump contract and trump is equal to card move suit) weight = 15 - (rank of card move) + suitAdd else weight = - (rank of card move) + suitAdd } else if (lowest card for partner to leading hand or for RHO in the suit played is higher than played card for LHO) weight = - (rank of card move) else if (LHO played card is higher than card played by the leading hand) { if (LHO move card has at least one equivalent card) weight = 20 - (rank of card move) else weight = 10 - (rank of card move) } else weight = - (rank of card move) } Hand-to-play is partner to trick leading hand if (trick winning card move) { if (hand-to-play void in the suit played by the leading hand) { if (card played by the leading hand is highest so far) { if (card by hand-to-play is trump and the suit played by the leading hand is not trump) weight = 30 - (rank of card move) + suitAdd else weight = 60 - (rank of card move) + suitAdd } else if (hand-to-play is on top by ruffing) weight = 70 - (rank of card move) + suitAdd else if (hand-to-play discards a trump but still loses) weight = 15 - (rank of card move) + suitAdd else weight = 30 - (rank of card move) + suitAdd } else weight = 60 - (rank of card move) } else { /* card move is not trick winning */ if (hand-to-play void in the suit played by the leading hand) { if (hand-to-play is on top by ruffing) weight = 40 - (rank of card move) + suitAdd else if (hand-to-play underruffs */ weight = -15 - (rank of card move) + suitAdd else weight = - (rank of card move) + suitAdd } else { if (the card by hand-to-play is highest so far) { if (rank of played card is second highest in the suit) weight = 25 else if (hand-to-play card has at least one equivalent card) weight = 20 - (rank of card move) else weight = 10 - (rank of card move) } else weight = -10 - (rank of card move) } } Hand-to-play is right hand opponent (RHO) to leading hand if (hand-to-play is void in leading suit) { if (LHO has current highest rank of the trick) { if (card move ruffs) weight = 14- (rank of card move) + suitAdd else weight = 30- (rank of card move) + suitAdd } else if (hand-to-play ruffs and wins) weight = 30- (rank of card move) + suitAdd else if (card move suit is trump, but not winning) weight = - (rank of card move) else weight = 14- (rank of card move) + suitAdd } else if (LHO has current winning move) { if (RHO ruffs LHO’s winner) weight = 24 - (rank of card move) else weight = 30- (rank of card move) } else if (card move superior to present winning move not by LHO) { weight = 30- (rank of card move) else { if (card move ruffs but still losing) weight = - (rank of card move) else weight = 14- (rank of card move) } 6.Algorithm to try early cutoff for generated moves After generating moves at the end of a trick, they are each checked to see if one of them will lead to a position that already is stored in the Transposition Table. Due to the processing overhead, this check is only made if the depth is 33 or more (i.e there are at least 33 cards in the position). Pseudo code: moveExists = TRUE; while (moveExists) { Make; depth = depth –1; RetrieveTTresult; if (hit in the transposition table) { Search returnsTRUE if value of the position is TRUE and player side to move, or FALSE if value of the position is FALSE and opponents side to move. Else: Increment weight of move with 100. } depth = depth +1; Undo; moveExists = NextMove; } The performance improvement for this enhancement is less than for the other enhancements. The number of generated nodes is roughly decreased by 10% and the search time is slighly decreased. 7.Storage and retrieval of position state data in the Transposition Table Positions stored in the Transposition Table always consist of completed tricks. Positions stored start at depth=4, then 8,12, and so on. The information stored is information on won cards, the suit lengths of the hands, the hand to play the leading card in the position and upper and lower bounds for the number of future tricks to be taken by the side of the player. Starting from issue 1.1.8, each ”winning cards node” contain all winning cards for one suit after an idea by Joël Bradmetz. This new solution is faster. 7.1 Transposition Table storing winning card ranks For the outcome of played tricks, only card ranks that are winning due to their ranks matter: Assume that the last two tricks of a deal without trumps looks like the following: Trick 12: Leading hand North plays heart A, East, South and West follow by hearts Q, 9 and 7 respectively. Trick 13: North then leads spade A, the other hands plays diamonds J, 8,3 in that order. In trick 12, heart A wins by rank. In trick 13, spade A wins but not by rank. The sequence of cards could have been the following without changing the outcome: Trick 12: heart A, heart x, heart x, heart x Trick 13: spade x, diamond x, diamond x, diamond x where x is any rank below lowest winning rank. The cards that win by rank are recorded during the search and backed up similarly to the search value. If a card wins by rank and there are equivalent cards, e.g. only spade A is searched from a sequence of AKQ, then also the other cards K and Q must be recorded as having won by rank. The cards winning by rank are stored in the Transposition Table as relative ranks, however any rank larger than the lowest winning rank in the suit are also stored as ”winning ranks”. Using relative ranks rather than absolute ranks considerably increases the number of positions that match this Transposition Table entry: As an example, assume that there are only 4 cards left in a suit, A, Q, 9, 7 where each hand has one card in the suit. Then any combination of ranks, e.g. 8, 6, 3, 2 that preserves the relative order of ranks between hands will cause a match. In the state position information absolute ranks are used, it is only in the Transposition Table where the ranks are stored as relatives. 7.2 Backing up the winning ranks At the search termination, either at the last trick or at a cutoff, the cards that have won by rank are backed up in the search tree together with the search value. As this information propagates upwards, it is aggregated with backed up information from other tree branches. At a search cutoff, MergeMoveData merges the information (V is a union): (winning ranks of all suits for current depth) = (winning ranks of all suits for depth - 1) V (possible winning rank for the current move causing the cutoff) For each new move not causing cutoff, MergeAllMovesData merges: (winning ranks of all suits for current depth) = (winning ranks of all suits for current depth) V (winning ranks of all suits for depth - 1) V (possible winning rank for the current move) 7.3 Checking the current position for a Transposition Table entry match The "Transposition Table" has a tree structure rather than a table, consisting of 2 interconnected trees. For deciding if there is a match, input is the position state data, including the cards left to play and the current leading hand. There are ”root pointers” per number of tricks left and per leading hand which each points to the root of a tree of ”suit lengths combination” nodes. Each such node includes a 64-bit code that uniquely defines one combination of suit lengths for the hands. The nodes are ordered such that the value of the 64-bit code in a parent node is higher than the 64-bit code of its left child but lower than the 64-bit code of its right child. So to find the node with the suit lengths combination for the actual position, a binary search is made. The basic binary search algorithm is described in [Knuth]. Each ”suit length combination node” points to the root of a tree consisting of ”winning cards nodes”, ie. cards that win by rank. (So the Transposition Table is really a number of trees, a forest.) When a position is checked for a possible Transposition Table match, a tree branch is selected consisting of 4 subsequent ”winning cards nodes”, each ”winning cards node” includes an aggregate of all winning cards for one suit. This branch is followed as long as the ”winning cards” also can be found in the current position. (Note that the ranks of the ”winning card nodes” are relative, so the ranks of the current position must first be translated from absolute to relative ranks.) When the ”winning cards node” no longer matches with the current position and there is no other alternative ”winning cards node” that fits, then the search backs up and tries an alternative ”winning cards node” on a higher level. When the last of the 4 subsequent ”winning cards nodes” containing clubs is reached, it points to a ”set of positions node”. Its stored upper and lower value bounds are checked against the number of tricks won so far by the player’s side and the target value. The following conditions are then checked, assuming that it is the North/South side that is the player’s side: If the sum of the stored lower value bound and the number of tricks won so far for the player’s side is equal or larger than target, then target can be reached for the player’s side in the current position. Search on this depth is terminated and TRUE is returned. If the sum of the stored upper value bound and the number of tricks won so far for the player’s side is less than target, then reaching target can be prevented by the opponents to the player’s side in the current position. Search on this depth is terminated and FALSE is returned. If instead it is East/West that is the player’s side, the following conditions apply: If the sum of number of tricks remaining and the number of tricks won so far for the player’s side minus the upper value bound is equal or larger than target, then target can be reached for the player’s side in the current position. Search on this depth is terminated and TRUE is returned. If the sum of number of tricks remaining and the number of tricks won so far for the player’s side minus the lower value bound is less than target, then reaching target can be prevented by the opponents to the player’s side in the current position. Search on this depth is terminated and FALSE is returned. For all other cases, the search continues for the current depth. For example, take the previous example with 2 tricks remaining with spade rank order 1 at North. (Rank order 1 is highest rank.) The hearts have rank orders 1 at North, 2 at East, 3 at South and 4 at West. The diamond rank orders are orders 1 at East, 2 at South and 3 at West. North is leading hand. The ”root pointer” is now defined by the number of tricks remaining (=2) and North as leading hand. The ”root pointer” points to the root node of its ”suit lengths combination” tree. The 64-bit integer coded from the suit lengths for all suits and hands is now searched within the tree. When the node is found with matching 64-bit suit lengths code, this node will point to the root of its ”winning card” tree. This pointer points to a "winning cards node" containing spade rank order 1 at North which fits with the current position. This ”winning cards node” points to another "winning cards node" containing hearts rank orders 1 at North and 2 at East which also fits the current position. Next ”winning cards node” pointed to contains diamonds order 1 at South, which does not match the current position. However, there is an alternative ”winning cards node” that has diamonds order 1 at East, which fits. (If there had been no alternative ”winning cards node” which fitted, the search had backed up to the previous ”winning cards node” to see if there was an alternative ”winning cards node” on this level which also fitted.) The next ”winning cards node” pointed to is for clubs. This node is empty, which fits the current position which have no clubs. This ”winning cards node” points to a "set of positions node” which have upper and lower value bounds defined. The conditions for these bounds are assumed to be fulfilled causing search termination on this depth, as described earlier. The usage of upper and lower value bounds in transposition tables is described in [Chang] and [Kupferschmid, Helmert]. The ”suit lengths combination” node includes: The suit lengths combination as a 64-bit integer. A pointer to the top ”winning cards node”. A pointer to next left ”suit lengths combination node” in the binary tree. A pointer to next right ”suit lengths combination node” in the binary tree. The ”winning cards node” includes: The hands of the relative ranks for each winning card of the actual suit. A pointer to the next winning cards node required to achieve a Transposition Table match for this branch of the tree. A pointer to the previous winning cards node. A pointer to the next alternative winning cards node that leads to a Transposition Table match in an alternative tree branch. A pointer to the "set of positions node". The "set of positions node” includes: An upper and a lower bound for the winning tricks of the North/South side. These values are used to determine whether or not a search cutoff can be done. The lowest winning rank per suit, expressed as relative rank. The suit and rank for the currently best move. After a Transposition Table match, the current position may later be part of a position that will be stored in the Transposition Table. Therefore, the stored winning ranks in the Transposition Table must be included in the state information of the current position. However, the winning ranks cannot be taken as is, because they are stored as relative ranks which now must be converted to absolute ranks in the current position. This is done using the lowest winning relative rank for each suit that is stored in the ”set of positions” node that gave the Transposition Table match: The aggregated set of (absolute) ranks for each suit in the current position is filtered using the stored information on the lowest winning relative rank. The winning ranks for each suit is then the aggregated set with only the number of highest ranks implied by the stored lowest winning relative rank in the ”set of positions” node. E.g. if the aggregated rank set for spades is A J 9 4 2 and lowest winning relative rank is order=2, then winning ranks are A J. 7.4 Building a new entry in the Transposition Table When the value of the current position is known and it is the end of a trick (except the last), position state information is collected for storage in the Transposition Table. The ranks of the backed up winning cards are converted from absolute to relative. For each suit, it is determined which winning rank that is lowest. The relative ranks then stored in the new Transposition Table entry are all ranks above and including the lowest rank, filling out any ”holes” in the ranks that might have been present. The trees of the Transposition Table are searched starting from the ”root pointer” and additional nodes are inserted corresponding to the current position. First, the suit lengths of the current position are used to find a ”suit lengths combination node” or to create a new such node if it does not exist already. The next step is to search for a ”winning card node” that has the ”suit length combination node” as parent. This ”winning card node” has then winning cards for spades. If no such node yet exists, ”winning card nodes”, one for each suit, are created using the winning cards of the current position. Each such node includes all winning cards for one of the suits. Then, a ”set of positions” node is created. This node is pointed to from the last created ”winning card node” created for the winning cards of clubs. Otherwise, if there already exists a matching ”winning card node” with the ”suit length combination node” as parent, it is checked whether or not the ”winning card nodes” in a subsequent tree branch already created for hearts, diamonds and clubs also are matched with the current position. If such a sequence of nodes can be found, the upper or lower bound in the connected ”set of positions node” may be updated to allow for an increased number of cutoffs: If the current position upper value bound is less than the stored upper value bound, the stored value is updated with the current position value. If the current position lower value bound is larger than the stored lower value bound, the stored value is updated with the current position value. In case a matching ”winning card node” cannot be found, a new ”winning card node” is created and linked to the last matching node. E.g. if existing ”winning card nodes” for spades and hearts match the current position, but no node match for diamonds, then a ”winning cards node” for diamonds is created and linked to the previous ”winning cards node” for hearts. Then a clubs ”winning cards node” and a ”set of positions node” are created. References James Dow Allen: Source code for a simple DDS. http://freepages.genealogy.rootsweb.com/~jamesdow/Tech/dbldum.htm Matthias Brill: DDS algorithms description (in German) and DDS source code. http://linux.softpedia.com/get/Science-and-Engineering/Artificial-Intelligence/cddsolve-20055.shtml Ming-Sheng Chang: DDS algorithms description. cs.nyu.edu/web/Research/TechReports/TR1996-725/TR1996-725.ps.gz Ed Colley: DDS source code and DDS executable. http://freefinesse.sourceforge.net/ Matthew L. Ginsberg: DDS algorithms description. http://www.cs.cmu.edu/afs/cs/project/jair/pub/volume14/ginsberg01a.pdf Dan Hirschberg: DDS algorithms description and DDS executable (MS DOS, cannot run in XP?) http://www.ics.uci.edu/~dan/bridge/index.html Alexey Slovesnov: DDS source code and DDS executable. Judea Pearl: Asymptotic properties of minimax trees and game search precedures. Artificial Intelligence 14(2):113-138. [Pearl 1980] Aske Plaat, Jonathan Schaeffer, Wim Pijls and Arie de Bruin: Exploiting graph properties of game trees. In Proceedings of the Thirteenth National Conference on Artificial Intelligence, pages 234-239, 1996 [Plaat et al.] Hans Kuijf, personal communication. Pedja Stanojevic, personal communication. Knuth: The art of computer programming, Vol. 3, Searching and Sorting, chapter 6.2.2, Algorithm T. Sebastian Kupferschmid, Malte Helmert: A Skat Player Based on Monte Carlo Simulation. Joël Bradmetz, personal communication. http://jibe-bridge.perso.cegetel.net/ dds-2.4.2+ddd105/ddd/0000775000401600040160000000000012267505752012056 5ustar cbecbedds-2.4.2+ddd105/ddd/deals.gib0000664000401600040160000000257710554446617013645 0ustar cbecbe{name=cpt-47 The following deal is from page 47 of 'Card Play Technique' by Norman Squire. The play and analysis given there agrees completely with DDA. Bidding: W N E S - - 1C dbl no 2H etc Lead W: C8 South reaches 3NT after East opened with 1C. Dummy plays C9, east CT and south wins with CK. South enters dummy with HK to lead a diamond, east playing low, the DK winning. South plays another heart to the ace, intending to play another diamond to establish the suit, but on this east discards the DA. All south can do is take the spade finesse and cash his tricks, going down one. If east does not play DA, south makes 4NT. Note that 4NT by north cannot be beaten. } j95.t8632.j65.85 t862.ak54.73.q92 k743.j.a98.ajt76 aq.q97.kqt42.k43 {name=cpt-47-3t played=c8.c9.ct.ck-h7.h2.hk.hj-d3.d8.dk.d5 first 3 tricks only } j95.t8632.j65.85 t862.ak54.73.q92 k743.j.a98.ajt76 aq.q97.kqt42.k43 {name=cpt-47-3t+3c played=c8.c9.ct.ck-h7.h2.hk.hj-d3.d8.dk.d5-h9.h3.ha south is in 3NT, this is the position after the first 3 tricks and 3 cards of 4-th trick, the killer play by east is to discard ace of diamonds, anything else gives south at least 10 tricks } j95.t8632.j65.85 t862.ak54.73.q92 k743.j.a98.ajt76 aq.q97.kqt42.k43 {name=cpt-47-le leader=e declarer north } j95.t8632.j65.85 t862.ak54.73.q92 k743.j.a98.ajt76 aq.q97.kqt42.k43 dds-2.4.2+ddd105/ddd/license0000664000401600040160000004363210554446617013434 0ustar cbecbe GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. dds-2.4.2+ddd105/ddd/giblib.cpp0000664000401600040160000005163510567641166014025 0ustar cbecbe/* ************************************************************************** giblib.cpp giblib reader and state for bridge C/C++ programs PM Cronje June 2006 PM Cronje 13-Jul-2006 add deal genearator Copyright 2006 P.M.Cronje This file is part of the Double Dummer Driver (DDD). DDD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. DDD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with DDD; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ************************************************************************** */ #include #include #include #include #include #include "giblib.h" // ***************************************************************************** cGIBLib::cGIBLib() { pszComment = (char*)realloc(0,GIBLIB_LENLINE*sizeof(char)); pszName = (char*)realloc(0,sizeof(char)); pszName[0] = '\0'; nPlayed = 0; nLine = 0; pRNG = cRNG::createRNG(eRNG_MT,0); } // cGIBLib::cGIBLib // ***************************************************************************** cGIBLib::~cGIBLib() { pszComment = (char*)realloc(pszComment,0); pszName = (char*)realloc(pszName,0); if(pRNG) delete pRNG; } // cGIBLib::~cGIBLib // ***************************************************************************** bool cGIBLib::generateDeal(int ntrick) { int lsuit[52], lcard[52]; int player, suit, card, icard, ncard, ndeck; if(pRNG == 0) { sprintf(szErrMsg,"*** error: create RNG\n"); return false; } if((ntrick < 1) || (ntrick > 13)) { sprintf(szErrMsg,"*** error: generateDeal ntrick=%d must be >=1 and <=13\n", ntrick); return false; } memset(mPlayerSuit,0,16*sizeof(ushort)); player = 0; // set up a sorted deck icard = 0; for(suit=0; suit<4; suit++) { for(card=0; card<13; card++) { lsuit[icard] = suit; lcard[icard] = card; icard++; } } if(ntrick < 1) ntrick = 1; if(ntrick > 13) ntrick = 13; ncard = 4 * ntrick; ndeck = 52; while(ncard) { if(ncard == 1) icard = 0; else icard = (int)pRNG->randomUint(ndeck); // add new card given by lsuit[icard] and lcard[icard] setBit(mPlayerSuit[player][lsuit[icard]],lcard[icard]); // shorten deck (remove this card) if(icard < ndeck-1) { memmove(lsuit+icard,lsuit+icard+1,(ndeck-1-icard)*sizeof(int)); memmove(lcard+icard,lcard+icard+1,(ndeck-1-icard)*sizeof(int)); } ncard--; ndeck--; player = ((player+1)%4); } return true; } // cGIBLib::generateDeal // ***************************************************************************** enum eCard cGIBLib::getCard(char chcard) { if(tolower(chcard) == 'a') return eCARD_A; else if(tolower(chcard) == 'k') return eCARD_K; else if(tolower(chcard) == 'q') return eCARD_Q; else if(tolower(chcard) == 'j') return eCARD_J; else if(tolower(chcard) == 't') return eCARD_10; else if(isdigit(chcard)) { if(((int)chcard >= (int)'2') && ((int)chcard <= (int)'9')) return (enum eCard)(14 - (int)chcard + (int)'0'); } return eCARD_NONE; } // cGIBLib::getCard // ***************************************************************************** bool cGIBLib::getOptions() { char *pchend; int suit, card; pchend = strstr(pszComment,"name="); if(pchend) setName(pchend+5); else pszName[0] = '\0'; pchend = strstr(pszComment,"trumps="); if(pchend) { if(tolower(pchend[7]) == 's') Trumps = 0; else if(tolower(pchend[7]) == 'h') Trumps = 1; else if(tolower(pchend[7]) == 'd') Trumps = 2; else if(tolower(pchend[7]) == 'c') Trumps = 3; else if(tolower(pchend[7]) == 'n') Trumps = 4; else { sprintf(szErrMsg,"*** error: invalid trumps='%c' at line %d\n", pchend[7],nLine); return false; } } pchend = strstr(pszComment,"leader="); if(pchend) { if(tolower(pchend[7]) == 'w') Leader = 0; else if(tolower(pchend[7]) == 'n') Leader = 1; else if(tolower(pchend[7]) == 'e') Leader = 2; else if(tolower(pchend[7]) == 's') Leader = 3; else { sprintf(szErrMsg,"*** error: invalid leader='%c' at line %d\n", pchend[7],nLine); return false; } } pchend = strstr(pszComment,"played="); if(pchend) { pchend += 7; nPlayed = 0; for(;;) { while((pchend[0]=='.') || (pchend[0]=='-')) pchend++; if(tolower(pchend[0]) == 's') suit = 0; else if(tolower(pchend[0]) == 'h') suit = 1; else if(tolower(pchend[0]) == 'd') suit = 2; else if(tolower(pchend[0]) == 'c') suit = 3; else if((pchend[0]==' ')||(pchend[0]=='}')||(pchend[0]=='\n')) break; else { sprintf(szErrMsg,"*** error: invalid suit='%c' at line %d\n", pchend[0],nLine); return false; } pchend++; card = getCard(pchend[0]); if(card == eCARD_NONE) { sprintf(szErrMsg,"*** error: invalid card='%c' at line %d\n", pchend[0],nLine); return false; } if(nPlayed >= 51) { sprintf(szErrMsg,"*** error: too many cards at line %d\n",nLine); return false; } SuitPlayed[nPlayed] = suit; CardPlayed[nPlayed] = card; nPlayed++; pchend++; } } return true; } // cGIBLib::getOptions // ***************************************************************************** bool cGIBLib::getTricks(int i, int *pleader, int *ptrumps, int *pntrick) { // defaults *pleader = ePLAYER_WEST; *ptrumps = eCONTRACT_NOTRUMP; *pntrick = 0; if((i < 0) || (i >= 20)) return false; // leader *pleader = (3 - (i % 4)); // trumps *ptrumps = (i / 4); if(*ptrumps == 0) *ptrumps = eCONTRACT_NOTRUMP; else (*ptrumps)--; // number of tricks; *pntrick = -1; char *pch = szTricks + i; if(isdigit(*pch)) *pntrick = (*pch - '0'); else if(isxdigit(*pch)) *pntrick = (toupper(*pch) - 'A' + 10); if((*pntrick < 0) || (*pntrick > 13)) { *pntrick = 0; return false; } else return true; } // cGIBLib::getTricks() // ***************************************************************************** int cGIBLib::numCard() { return (nPlayerCard(0)+nPlayerCard(1)+ nPlayerCard(2)+nPlayerCard(3));} int cGIBLib::nPlayerCard(int pl) { return bitCount(mPlayerSuit[pl][0])+bitCount(mPlayerSuit[pl][1]) +bitCount(mPlayerSuit[pl][2])+bitCount(mPlayerSuit[pl][3]); } // ***************************************************************************** bool cGIBLib::playCard(int suit, int card) { int player, pl, c; if((suit<0) || (suit>3) || (card<0) || (card>12)) { sprintf(szErrMsg,"*** error: invalid playcard suit=%d card=%d\n", suit,card); return false; } // find player player = -1; for(pl=0; pl<4; pl++) { if(isBit(mPlayerSuit[pl][suit],card)) { player = pl; break; } } if(player == -1) { sprintf(szErrMsg,"*** error: card %c%c not found in hands\n", chSUIT[suit],chCARD[card]); return false; } // set/test player if((suit == SuitPlayed[0]) && (card == CardPlayed[0])) Player = Leader = player; else { // check the player, it must be same as current player if(player != Player) { sprintf(szErrMsg,"*** error: wrong player(%c) for card %c%c\n", chPLAYER[player],chSUIT[suit],chCARD[card]); return false; } } // player must follow suit if( (nTrickCard != 0) && bitCount(mPlayerSuit[player][SuitLed]) && (suit != SuitLed)) { sprintf(szErrMsg,"*** error: card %c%c is not following suit led %c\n", chSUIT[suit],chCARD[card],chSUIT[SuitLed]); return false; } // update the player's cards clearBit(mPlayerSuit[player][suit],card); if((nTrickCard % 4) == 0) { // first card of trick, remember suitled and card played SuitLed = suit; TrickStart = 4 * nTrick; } // set this player PlayerPlayed[4*nTrick+nTrickCard] = player; SuitPlayed[4*nTrick+nTrickCard] = suit; CardPlayed[4*nTrick+nTrickCard] = card; nTrickCard++; if(nTrickCard == 4) { // end of trick, update leader and tricks c = TrickStart; int winningplayer = PlayerPlayed[c]; int winningsuit = SuitPlayed[c]; int winningcard = CardPlayed[c]; for(c=TrickStart+1; c 4) { sprintf(szErrMsg,"*** error: deal too many players\n"); return false; } else if(pc[0] == '\0') break; else if(pc[0] == ' ') { // next player pl = ((pl+1) & 3); s = eSUIT_SPADE; nplayer++; } else if(*pc == '.') { // next suit s++; if(s > eSUIT_CLUB) { sprintf(szErrMsg,"*** error: deal too many suits\n"); return false; } } else { if(bitCount(mPlayerSuit[pl][s]) >= 13) { sprintf(szErrMsg,"*** error: more than 13 cards in suit at line %d\n", nLine); return false; } c = getCard(pc[0]); if(c == eCARD_NONE) { sprintf(szErrMsg,"*** error: invalid deal card %c line %d\n", pc[0],nLine); return false; } if(isBit(mPlayerSuit[pl][s],c)) { sprintf(szErrMsg,"*** error: duplicate card %c player %c\n", chCARD[c],chPLAYER[pl]); return false; } if(isBit(msuit[s],c)) { sprintf(szErrMsg,"*** error: duplicate card %c in more than one hand\n", chCARD[c]); return false; } setBit(msuit[s],c); setBit(mPlayerSuit[pl][s],c); } pc++; } // test equal number of cards in each hand if( (nPlayerCard(0) != nPlayerCard(1)) || (nPlayerCard(0) != nPlayerCard(2)) || (nPlayerCard(0) != nPlayerCard(3))) { sprintf(szErrMsg,"*** error: different number of cards in hands line %d\n", nLine); return false; } // play specified cards if(setPlayed() == false) return false; return true; } // cGIBLib::setDeal // ****************************************************************************** bool cGIBLib::setGeneratedDeal() { int pos, player, suit, c; ushort m; reset(); pos = 0; for(player=0; player<4; player++) { for(suit=0; suit<4; suit++) { if(suit > 0) { szDeal[pos] = '.'; pos++; } m = mPlayerSuit[player][suit]; while(m) { c = leastSignificant1Bit(m); clearBit(m,c); szDeal[pos] = chCARD[c]; pos++; } } szDeal[pos] = ' '; pos++; } szDeal[pos-1] = '\0'; if(setDeal() == false) return false; if(setPlayed() == false) return false; return true; } // cGIBLib::setGeneratedDeal // ***************************************************************************** bool cGIBLib::setPlayed() { int i, nplayed; Player = Leader; nTrick = nTrickCard = nTrickSN = nTrickWE = 0; nplayed = nPlayed; nPlayed = 0; for(i=0; i #include #include #include #include #include #include "timer.h" // ***************************************************************************** // timer workaround for Windoze, // must define _WIN32 for compilation // ***************************************************************************** #if defined(_WIN32) typedef struct sFileTime { unsigned int dwLowDateTime; unsigned int dwHighDateTime; }; extern "C" { void _stdcall GetSystemTimeAsFileTime(struct sFileTime *pft); } void gettimeofday(struct timeval* p, void* pv); void gettimeofday(struct timeval* p, void* pv) { union { long long ns100; // time since 1 Jan 1601 in 100ns units struct sFileTime ft; } now; GetSystemTimeAsFileTime(&(now.ft)); p->tv_usec = (int)((now.ns100 / 10LL) % 1000000LL); p->tv_sec = (int)((now.ns100 - (116444736000000000LL))/10000000LL); } #endif // ***************************************************************************** // cTimer // ***************************************************************************** cTimer::cTimer() { bStarted = false; dElapsed = prevdElapsed = deltaElapsed = 0.0; } // cTimer::cTimer // ***************************************************************************** cTimer::~cTimer() { stop(); } // cTimer::~cTimer // ***************************************************************************** void cTimer::check() { // find elapsed statistics if(bStarted) { getTimerInfo(&dElapsed); deltaElapsed = dElapsed - prevdElapsed; prevdElapsed = dElapsed; dElapsed -= dElapsed0; } else start(); } // cTimer::check // ***************************************************************************** void cTimer::getFormattedTime(char sztime[32]) { // DD-MON-YYYY HH:MM:SS time_t timeval; struct tm *ptm; // find the current date and time time(&timeval); ptm = localtime(&timeval); strftime(sztime,21,"%d-%b-%Y %H:%M:%S",ptm); } // cTimer::getFormattedTime // ***************************************************************************** void cTimer::getTimerInfo(double *pdelapsed) { struct timeval tv; // elapsed gettimeofday(&tv,0); *pdelapsed = (double)tv.tv_sec + 0.000001 * (double)tv.tv_usec; if(*pdelapsed < 0.000001) *pdelapsed = 0.000001; } // cTimer::getTimerInfo // ***************************************************************************** void cTimer::start() { getTimerInfo(&dElapsed0); dElapsed = dElapsed0; prevdElapsed = dElapsed; deltaElapsed = 0.0; bStarted = true; } // cTimer::start // ***************************************************************************** void cTimer::stop() { if(bStarted) { check(); bStarted = false; } } // cTimer::stop // ***************************************************************************** dds-2.4.2+ddd105/ddd/defs.cpp0000664000401600040160000001467110567641166013515 0ustar cbecbe/* ************************************************************************** defs.cpp bridge definitions for C/C++ programs PM Cronje June 2006 Copyright 2006 P.M.Cronje This file is part of the Double Dummer Driver (DDD). DDD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. DDD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with DDD; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ************************************************************************** */ #include #include #include #include "defs.h" const char *szPLAYER[4] = {"west", "north", "east", "south"}; const char chPLAYER[4] = {'W', 'N', 'E', 'S'}; const char *szSUIT[4] = {"spades", "hearts", "diamonds", "clubs"}; const char chSUIT[4] = {'S', 'H', 'D', 'C'}; const char *szCONTRACT[5] = {"spades","hearts","diamonds","clubs","notrump"}; const char chCARD[13] = {'A','K','Q','J','T','9','8','7','6','5','4','3','2'}; const ushort usMASK[16] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 }; const ushort usNotMASK[16] = { 0xfffe, 0xfffd, 0xfffb, 0xfff7, 0xffef, 0xffdf, 0xffbf, 0xff7f, 0xfeff, 0xfdff, 0xfbff, 0xf7ff, 0xefff, 0xdfff, 0xbfff, 0x7fff }; const unsigned int ulMASK[32] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000 }; const unsigned int ulNotMASK[32] = { 0xfffffffe, 0xfffffffd, 0xfffffffb, 0xfffffff7, 0xffffffef, 0xffffffdf, 0xffffffbf, 0xffffff7f, 0xfffffeff, 0xfffffdff, 0xfffffbff, 0xfffff7ff, 0xffffefff, 0xffffdfff, 0xffffbfff, 0xffff7fff, 0xfffeffff, 0xfffdffff, 0xfffbffff, 0xfff7ffff, 0xffefffff, 0xffdfffff, 0xffbfffff, 0xff7fffff, 0xfeffffff, 0xfdffffff, 0xfbffffff, 0xf7ffffff, 0xefffffff, 0xdfffffff, 0xbfffffff, 0x7fffffff }; // ***************************************************************************** int fromHex(char ch) { if(isdigit(ch)) return ((int)tolower(ch) - (int)'0'); else return ((int)tolower(ch) - (int)'a' + 10); } // fromHex // ***************************************************************************** char toHex(int i) { if(i < 10) return (char)(i + '0'); else return toupper((char)(i - 10 + (int)'a')); } // toHex // ***************************************************************************** // initialization of static arrays // - BitsInByte[256] // count of 1-bits in byte // - MSBitInByte[256] // most significant bit in byte static bool initBitsInByte(int bits[256], int msb[256]) { int i, n, m; bits[0] = msb[0] = 0; // set bits in byte for(i=1; i<256; i++) { n = 0; m = i; while(m) { n++; m = (m & (m-1)); // strip right-most bit }; bits[i] = n; } // most significant bit in byte for(i=1; i<256; i++) { n = 0; m = i; while(m) { n++; m >>= 1; }; msb[i] = n-1; } return true; } // initBitsInChar // ***************************************************************************** static int BitsInByte[256]; static int MSBitInByte[256]; static bool bInitBitsInByte = initBitsInByte(BitsInByte,MSBitInByte); // ***************************************************************************** int bitCount(ushort m) { return (BitsInByte[m & 0x00ff] + BitsInByte[(m >> 8) & 0x00ff]); } // bitCount // ***************************************************************************** int leastSignificant1Bit(ushort m) { m = (ushort)((ushort)m ^ ((ushort)m - 1)); return bitCount(m) - 1; } // leastSignificant1Bit // ***************************************************************************** int mostSignificant1Bit(ushort m) { /* if(m & 0xff00) return (8 + MSBitInByte[(m >> 8) & 0x00ff]); else return MSBitInByte[m]; */ register unsigned int x = (m | (m >> 1)); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); //x = (x & (~(x >> 1))); return bitCount(x) - 1; } // mostSignificant1Bit // ***************************************************************************** void clearBit(ushort &m, int ibit) { m &= usNotMASK[ibit];} bool isBit(ushort m, int ibit) { return (m & usMASK[ibit]);} void setBit(ushort &m, int ibit) { m |= usMASK[ibit];} /* ************************************************************************** */ char *format(char str[], char sz[]); char *format64(unsigned long long number, char sz[]) { char str[32]; snprintf(str,31,"%llu",number); format(str,sz); return sz; } // format64 /* ************************************************************************** */ char *format(unsigned int number, char sz[]) { char str[32]; snprintf(str,31,"%u",number); format(str,sz); return sz; } // format /* ************************************************************************** */ char *format(char str[], char sz[]) { int len, n, istart, ndigit, i, pos; len = strlen(str); n = len / 3; if(3*n != len) n++; istart = pos = 0; for(i=0; i= 0.01) sprintf(sz,"%0.3lfm/s",1.0e-6*(double)count/elapsed); else strcpy(sz,"-.---m/s"); return sz; } // mPerSec /* ************************************************************************** */ dds-2.4.2+ddd105/ddd/rng.h0000664000401600040160000001744410567641166013030 0ustar cbecbe// ============================================================================= /* rng.cpp RNG - random number generators PMC 14-jun-2005 PMC 10-jul-2005 PMC 13-Jul-2006 updated, default is now MT Copyright 2005-2006 P.M.Cronje RNG is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. RNG is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RNG; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // ============================================================================= #ifndef RNG_H #define RNG_H typedef unsigned long long uint64; // ----------------------------------------------------------------------------- // Entropy test // ----------------------------------------------------------------------------- void initEnt(bool binmode); void addEnt(unsigned char *buf, int buflen); void endEnt(double *r_ent, double *r_chisq, double *r_mean, double *r_montepicalc, double *r_scc); void prtEnt(double r_chisq, double r_mean, double r_montepicalc, double r_scc); // ----------------------------------------------------------------------------- // Available RNG's // ----------------------------------------------------------------------------- enum eRNG { eRNG_QD1 = 0, // 'Quick and dirty' LCG eRNG_MT = 1, // Mersenne Twister MT19937_02 (default) eRNG_MTHR = 2, // 'Mother of all RNG' (Marsaglia) eRNG_WELL = 3, // WELL1024a, single seed with run-in eRNG_COUNT = 4 }; // enum eRNG // ----------------------------------------------------------------------------- // Description // ----------------------------------------------------------------------------- // // The QD1 is fast, but is only as good as an LCG can be, // it should only be used where true randomness is not required. // LCG = linear congruential generator. // // The other (mt/mthr/well) have been selected after many tests // using the TestU01 software of Ecuyer and Simard, and pass most // of the stringent tests for random number generators, failing only // occasionally at a significance level of a few parts in 0.001. // They all have extremely long periods and are recommended for any // serious simulation work requiring many millions of random numbers. // // The default generator is MT19937_02. // // The acronym WELL means 'Well Equidistributed Long-period Linear' // The generator WELL1024a has been modified to: // - initialize with a single seed // - generate equidistributed initial values // - run for 50,000 numbers to escape from the initial setup // // The generators mt/mthr are initialized from a single seed using a WELL. // // Speed (relative elapsed time for 10,000,000 numbers) // qd1 1.00 // mt 1.25 // mthr 1.90 // well 1.41 // // ----------------------------------------------------------------------------- extern const char *pszRNGGen[eRNG_COUNT]; extern const char *pszRNGGenList; extern const char *pszRNGGenDefault; enum eRNG const eRNGGenDefault = eRNG_MT; // ----------------------------------------------------------------------------- // forward declaration of derived classes // ----------------------------------------------------------------------------- class cRNG_QD1; class cRNG_WELL; class cRNG_Mother; class cRNG_MT19937; // ----------------------------------------------------------------------------- // cRNG - base class // ----------------------------------------------------------------------------- class cRNG { public: virtual ~cRNG() { } // set seed virtual void set(unsigned int useed) = 0; // generator name virtual char *getszRandom() = 0; // next random number virtual unsigned int random() = 0; // return random unsigned int, where 0 <= unsigned int < uirange virtual unsigned int randomUint(unsigned int urange); // creates an instance of cRNG, // specifying either eRNG or a string identifier pszrng, // if pszgen incorrectly specified creates a cRNG_MT // // erng pszrng // --------- -------- // eRNG_QD1 "qd1" // eRNG_MT "mt" // eRNG_MTHR "mthr" // eRNG_WELL "well" // // note: the object must be deleted after use static cRNG *createRNG(eRNG erng, unsigned int useed); static cRNG *createRNG(char *pszrng, unsigned int useed); enum eRNG getRNG() { return RNG;} const char *getpszGen() { return (const char*)szGen;} protected: eRNG RNG; char szGen[16]; unsigned int uSeed; }; // cRNG // ----------------------------------------------------------------------------- class cRNG_QD1 : public cRNG { public: cRNG_QD1(unsigned int useed=0) { set(useed);} // set virtual void set(unsigned int useed); // generator name virtual char *getszRandom() { return "QD1";} // next random number virtual unsigned int random(); unsigned int getSeed() { return uSeed;} protected: }; // cRNG_QD1 // ----------------------------------------------------------------------------- class cRNG_WELL : public cRNG { public: cRNG_WELL(unsigned int useed=0) { set(useed);} // set virtual void set(unsigned int useed); // generator name virtual char *getszRandom() { return "WELL1024u";} // next random number virtual unsigned int random(); protected: unsigned int state_i, STATE[32], z0, z1, z2; }; // cRNG_WELL // ----------------------------------------------------------------------------- class cRNG_Mother : public cRNG { public: cRNG_Mother(unsigned int useed=0) { set(useed);} // set virtual void set(unsigned int useed); // generator name virtual char *getszRandom() { return "Mother";} // next random number virtual unsigned int random(); protected: unsigned int smthr[4]; uint64 xm4, xm3, xm2, xm1, mcarry; }; // cRNG_Mother // ----------------------------------------------------------------------------- class cRNG_MT19937 : public cRNG { public: cRNG_MT19937(unsigned int useed=0) { set(useed);} // set virtual void set(unsigned int useed); // generator name virtual char *getszRandom() { return "MT19937";} // next random number virtual unsigned int random(); protected: unsigned int mti, U[624]; unsigned long mag01[2]; void initBySeed(unsigned int useed); void initByArray(unsigned int lenkey, unsigned int key[]); }; // cRNG_MT19937 // ----------------------------------------------------------------------------- #endif dds-2.4.2+ddd105/ddd/rng.cpp0000664000401600040160000004500310554446617013353 0ustar cbecbe// ============================================================================= /* rng.cpp RNG - random number generators PMC 14-jun-2005 PMC 06-jul-2005 PMC 13-jul-2006 Copyright 2005-2006 P.M.Cronje RNG is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. RNG is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RNG; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // ============================================================================= #include #include #include #include #include #include #include #include #include #include "rng.h" const char *pszRNGGen[eRNG_COUNT] = { "qd1", "mt", "mthr", "well" }; const char *pszRNGGenList = "qd1/mt/mthr/well"; const char *pszRNGGenDefault = "mt"; double dRAN_SCALE = 1.0 / (1.0+double((unsigned int)(0xFFFFFFFF))); // ***************************************************************************** // cRNG // ***************************************************************************** unsigned int cRNG::randomUint(unsigned int urange) { return (unsigned int)((double)urange * (double)random() * dRAN_SCALE); } // cRNG::randomUint // ***************************************************************************** cRNG *cRNG::createRNG(eRNG erng, unsigned int useed) { cRNG *prng; int rng; rng = (int)erng; if(rng == eRNG_QD1) prng = new cRNG_QD1(useed); else if(rng == eRNG_MTHR) prng = new cRNG_Mother(useed); else if (rng == eRNG_WELL) prng = new cRNG_WELL(useed); else // if(rng == eRNG_MT) // default prng = new cRNG_MT19937(useed); return prng; } // cRNG::createRNG(erng) // ***************************************************************************** cRNG *cRNG::createRNG(char *pszrng, unsigned int useed) { cRNG *prng; if(0 == strcasecmp(pszrng,"qd1")) prng = new cRNG_QD1(useed); else if(0 == strcasecmp(pszrng,"mthr")) prng = new cRNG_Mother(useed); else if (0 == strcasecmp(pszrng,"well")) prng = new cRNG_WELL(useed); else // if(0 == strcasecmp(pszrng,"mt")) // default prng = new cRNG_MT19937(useed); return prng; } // cRNG::createRNG(pszgen) // ***************************************************************************** // ranQD1 // ***************************************************************************** void cRNG_QD1::set(unsigned int useed) { uSeed = useed; RNG = eRNG_QD1; strcpy(szGen,pszRNGGen[RNG]); } unsigned int cRNG_QD1::random() { uSeed = ((unsigned int)(1664525L) * uSeed + (unsigned int)(1013904223L)); return uSeed; } // cRNG_QD1::random /* ************************************************************************** */ // equiDistribute1Bits /* ************************************************************************** */ unsigned int qd1(unsigned int *puseed) { *puseed = ((unsigned int)(1664525L) * (*puseed) + (unsigned int)(1013904223L)); return *puseed; } // qd1 unsigned int qd1Uint(unsigned int *puseed, unsigned int urange) { *puseed = ((unsigned int)(1664525L) * (*puseed) + (unsigned int)(1013904223L)); return (unsigned int)((double)urange * (double)(*puseed) * dRAN_SCALE); } // qd1Uint unsigned int count1Bits(unsigned int useed) { unsigned int mask, n1, i; // count the number of 1-bits mask = 0x00000001; n1 = 0; for(i=0; i<32; i++) { if(mask & useed) n1++; mask = (mask << 1); } return n1; } // count1Bits void reset1Bit(unsigned int u1bit, unsigned int *pu) { unsigned int mask, n, i; // find and zero the bit mask = 0x00000001; n = 0; for(i=0; i<32; i++) { if(mask & (*pu)) { if(n == u1bit) { *pu = ((*pu) & (~mask)); return; } n++; } mask = (mask << 1); } } // reset1Bit void set0Bit(unsigned int u0bit, unsigned int *pu) { unsigned int mask, n, i; // find and set the bit mask = 0x00000001; n = 0; for(i=0; i<32; i++) { if(0 == (mask & (*pu))) { if(n == u0bit) { *pu = ((*pu) | mask); return; } n++; } mask = (mask << 1); } } // set0Bit unsigned int equiDistribute1Bits(unsigned int u, unsigned int *puseed) { // if number of 1-bits in useed not 16, // if excess of 1-bits, randomly reset them to 0-bits // if excess of 0-bits, randomly set them to 1-bits unsigned int n1, i,ueq, ubit, n0; // count the number of 1-bits n1 = count1Bits(u); ueq = u; if(n1 > 16) { for(i=n1; i>16; i--) { ubit = qd1Uint(puseed,i); reset1Bit(ubit,&ueq); } } else if(n1 < 16) { n0 = 32 - n1; for(i=n0; i>16; i--) { ubit = qd1Uint(puseed,i); set0Bit(ubit,&ueq); } } return ueq; } // equiDistribute1Bits // ***************************************************************************** // WELL1024u // ***************************************************************************** #define MAT0POS(t,v) (v^(v>>t)) #define MAT0NEG(t,v) (v^(v<<(-(t)))) #define Identity(v) (v) #define W 32 #define R 32 #define M1 3 #define M2 24 #define M3 10 #define V0 STATE[ state_i ] #define VM1 STATE[(state_i+M1) & 0x0000001fU] #define VM2 STATE[(state_i+M2) & 0x0000001fU] #define VM3 STATE[(state_i+M3) & 0x0000001fU] #define VRm1 STATE[(state_i+31) & 0x0000001fU] #define newV0 STATE[(state_i+31) & 0x0000001fU] #define newV1 STATE[ state_i ] unsigned int cRNG_WELL::random() { z0 = VRm1; z1 = Identity(V0) ^ MAT0POS( 8, VM1); z2 = MAT0NEG (-19, VM2) ^ MAT0NEG(-14, VM3); newV1 = z1 ^ z2; newV0 = MAT0NEG(-11,z0) ^ MAT0NEG( -7,z1) ^ MAT0NEG(-13,z2); state_i = (state_i + 31) & 0x0000001fU; return STATE[state_i]; } // cRNG_WELL::random #undef W #undef R #undef M1 #undef M2 #undef M3 #undef V0 #undef VM1 #undef VM2 #undef VM3 #undef VRm1 #undef newV0 #undef newV1 void cRNG_WELL::set(unsigned int useed) { int j; unsigned int u, uqd1seed; RNG = eRNG_WELL; strcpy(szGen,pszRNGGen[RNG]); /* initialize using specified seed, set state mixing 0 and 1 bits */ uSeed = useed; state_i = 0; u = uqd1seed = useed; for (j = 0; j < 32; j++) { STATE[j] = equiDistribute1Bits(u,&useed); u = qd1(&useed); } /* run the generator for a while to escape from the seeded state */ for(j=0; j<50000; j++) random(); } // cRNG_WELL::set // ***************************************************************************** // Mother // ***************************************************************************** void cRNG_Mother::set(unsigned int useed) { RNG = eRNG_MTHR; strcpy(szGen,pszRNGGen[RNG]); uSeed = useed; smthr[0] = 5115; smthr[1] = 1776; smthr[2] = 1492; smthr[3] = 2111111111; xm1 = (uint64)smthr[0]; xm2 = (uint64)smthr[1]; xm3 = (uint64)smthr[2]; xm4 = (uint64)smthr[3]; unsigned int sum = xm1 + xm2 + xm3 + xm4; cRNG_WELL rng(uSeed); mcarry = (uint64)rng.randomUint(sum); } // cRNG_Mother::set unsigned int cRNG_Mother::random() { static uint64 am1 = (uint64)2111111111; static uint64 am2 = (uint64)1492; static uint64 am3 = (uint64)1776; static uint64 am4 = (uint64)5115; uint64 x = am1 * xm1 + am2 * xm2 + am3 * xm3 + am4 * xm4 + mcarry; xm1 = xm2; xm2 = xm3; xm3 = xm4; xm4 = (x & 0x00000000ffffffffULL); mcarry = (x >> 32); return (unsigned int)xm4; } // cRNG_Mother::random // ***************************************************************************** // mt19937ar // ***************************************************************************** // PMC20050619 - updated MT to mt19937ar /* Period parameters */ #define N 624 #define M 397 #define MATRIX_A 0x9908b0dfUL /* constant vector a */ #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ #define LOWER_MASK 0x7fffffffUL /* least significant r bits */ // static unsigned long mt[N]; /* the array for the state vector */ // static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ /* initializes mt[N] with a seed */ void cRNG_MT19937::initBySeed(unsigned int useed) { U[0]= useed & 0xffffffffUL; for (mti=1; mti> 30)) + mti); /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array p->U[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ U[mti] &= 0xffffffffUL; /* for >32 bit machines */ } } // cRNG_MT19937::initBySeed /* initialize by an array with array-length */ /* p->Key is the array for initializing keys */ /* p->LenKey is its length */ /* slight change for C++, 2004/2/26 */ void cRNG_MT19937::initByArray(unsigned int lenkey, unsigned int key[]) { int i, j, k; initBySeed(19650218UL); i=1; j=0; k = (N>lenkey ? N : lenkey); for (; k; k--) { U[i] = (U[i] ^ ((U[i-1] ^ (U[i-1] >> 30)) * 1664525UL)) + key[j] + j; /* non linear */ U[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ i++; j++; if (i>=N) { U[0] = U[N-1]; i=1; } if (j>=(int)lenkey) j=0; } for (k=N-1; k; k--) { U[i] = (U[i] ^ ((U[i-1] ^ (U[i-1] >> 30)) * 1566083941UL)) - i; /* non linear */ U[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ i++; if (i>=N) { U[0] = U[N-1]; i=1; } } U[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ } // initByArray void cRNG_MT19937::set(unsigned int useed) { unsigned int key[624]; int i; uSeed = useed; RNG = eRNG_MT; strcpy(szGen,pszRNGGen[RNG]); cRNG_WELL rng(useed); mag01[0] = 0x0UL; mag01[1] = MATRIX_A; for(i=0; i<624; i++) key[i] = rng.random(); initByArray(624,key); } // cRNG_MT19937::set /* generates a random number on [0,0xffffffff]-interval */ unsigned int cRNG_MT19937::random() { unsigned long y; if (mti >= N) { /* generate N words at one time */ int kk; if (mti == N+1) /* if not initalized, */ initBySeed(5489UL); /* a default initial seed is used */ for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; } for (;kk> 1) ^ mag01[y & 0x1UL]; } y = (U[N-1]&UPPER_MASK)|(U[0]&LOWER_MASK); U[N-1] = U[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; mti = 0; } y = U[mti++]; /* Tempering */ y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); return y; } // cRNG_MT19937::random #undef N #undef M #undef MATRIX_A #undef UPPER_MASK #undef LOWER_MASK // ***************************************************************************** // Entropy test // ***************************************************************************** double gammq(double a, double x); #define PI 3.14159265358979323846 #define log2of10 3.32192809488736234787 /* Treat input as a bitstream */ static bool binary = false; /* Bins to count occurrences of values */ static long ccount[256]; /* Total bytes counted */ static long totalc = 0; /* Probabilities per bin for entropy */ static double prob[256]; /* LOG2 -- Calculate log to the base 2 */ //static double log2(double x) //{ // return log2of10 * log10(x); //} /* Bytes used as Monte Carlo co-ordinates. This should be no more bits than the mantissa of your "double" floating point type. */ #define MONTEN 6 static int mp; static bool sccfirst; static unsigned int monte[MONTEN]; static long inmont, mcount; static double a, cexp, incirc, montex, montey, montepi, scc, sccun, sccu0, scclast, scct1, scct2, scct3, ent, chisq, datasum; void initEnt(bool binmode) { int i; /* Set binary/byte mode */ binary = binmode; /* Initialise for calculations */ ent = 0.0; /* Clear entropy accumulator */ chisq = 0.0; /* Clear Chi-Square */ datasum = 0.0; /* Clear sum of bytes for arithmetic mean */ mp = 0; /* Reset Monte Carlo accumulator pointer */ mcount = 0; /* Clear Monte Carlo tries */ inmont = 0; /* Clear Monte Carlo inside count */ incirc = 65535.0 * 65535.0; /* In-circle distance for Monte Carlo */ sccfirst = true; /* Mark first time for serial correlation */ scct1 = scct2 = scct3 = 0.0; /* Clear serial correlation terms */ incirc = pow(pow(256.0, (double) (MONTEN / 2)) - 1, 2.0); for (i = 0; i < 256; i++) ccount[i] = 0; totalc = 0; } // initEnt void addEnt(unsigned char *buf, int buflen) { unsigned char *bp = buf; int oc, c, bean; while (bean = 0, (buflen-- > 0)) { oc = *bp++; do { if (binary) c = !!(oc & 0x80); else c = oc; ccount[c]++; /* Update counter for this bin */ totalc++; /* Update inside/outside circle counts for Monte Carlo computation of PI */ if (bean == 0) { monte[mp++] = oc; /* Save character for Monte Carlo */ if (mp >= MONTEN) { /* Calculate every MONTEN character */ int mj; mp = 0; mcount++; montex = montey = 0; for (mj = 0; mj < MONTEN / 2; mj++) { montex = (montex * 256.0) + monte[mj]; montey = (montey * 256.0) + monte[(MONTEN / 2) + mj]; } if ((montex * montex + montey * montey) <= incirc) inmont++; } } /* Update calculation of serial correlation coefficient */ sccun = c; if (sccfirst) { sccfirst = false; scclast = 0; sccu0 = sccun; } else scct1 = scct1 + scclast * sccun; scct2 = scct2 + sccun; scct3 = scct3 + (sccun * sccun); scclast = sccun; oc <<= 1; } while (binary && (++bean < 8)); } } // addEnt void endEnt(double *r_ent, double *r_chisq, double *r_mean, double *r_montepicalc, double *r_scc) { int i; /* Complete calculation of serial correlation coefficient */ scct1 = scct1 + scclast * sccu0; scct2 = scct2 * scct2; scc = totalc * scct3 - scct2; if (scc == 0.0) scc = -100000; else scc = (totalc * scct1 - scct2) / scc; /* Scan bins and calculate probability for each bin and Chi-Square distribution */ cexp = totalc / (binary ? 2.0 : 256.0); /* Expected count per bin */ for (i = 0; i < (binary ? 2 : 256); i++) { prob[i] = (double) ccount[i] / totalc; a = ccount[i] - cexp; chisq = chisq + (a * a) / cexp; datasum += ((double) i) * ccount[i]; } /* Calculate entropy */ for (i = 0; i < (binary ? 2 : 256); i++) { if (prob[i] > 0.0) ent += prob[i] * log2(1 / prob[i]); } /* Calculate Monte Carlo value for PI from percentage of hits within the circle */ montepi = 4.0 * (((double) inmont) / mcount); /* Return results through arguments */ *r_ent = ent; *r_chisq = chisq; *r_mean = datasum / totalc; *r_montepicalc = montepi; *r_scc = scc; } // endEnt void prtEnt(double r_chisq, double r_mean, double r_montepicalc, double r_scc) { // probability that observed chi^2 will exceed the value chi^2 // by chance EVEN for a correct model: // Q(chi^2,nu) = gammaq(nu/2,chi^2/2); // double probq = 100.0 * gammq(127.5,0.5*r_chisq); printf(" %ss,Entropy,Chi-square,Mean,Monte-Carlo-Pi,Serial-Correlation\n", binary ? "bit" : "byte"); printf(" %ld,%f,%.1f(%.2f%%),%f,%f(%.2f%%),%f\n", //totalc,ent,r_chisq,100.0*chip,r_mean, totalc,ent,r_chisq,probq,r_mean, r_montepicalc,100.0*(r_montepicalc-PI),r_scc); } // prtEnt // ***************************************************************************** double gammln(float xx) { double x, y, tmp, ser; static double cof[6] = { 76.18009172947146, -86.50532032941677, 24.01409824083091, -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5 }; int j; y=x=xx; tmp=x+5.5; tmp -= (x+0.5)*log(tmp); ser=1.000000000190015; for (j=0;j<=5;j++) ser += cof[j]/++y; return -tmp+log(2.5066282746310005*ser/x); } // gammln // ***************************************************************************** #define ITMAX 100 #define EPS 3.0e-7 #define FPMIN 1.0e-30 void gcf(double *gammcf, double a, double x, double *gln) { int i; double an, b, c, d, del, h; *gln=gammln(a); b=x+1.0-a; c=1.0/FPMIN; d=1.0/b; h=d; for (i=1;i<=ITMAX;i++) { an = -i*(i-a); b += 2.0; d=an*d+b; if (fabs(d) < FPMIN) d=FPMIN; c=b+an/c; if (fabs(c) < FPMIN) c=FPMIN; d=1.0/d; del=d*c; h *= del; if (fabs(del-1.0) < EPS) break; } if (i > ITMAX) { printf("*** error %s: a too large, ITMAX too small\n",__func__); exit(1); } *gammcf=exp(-x+a*log(x)-(*gln))*h; } // gcf #undef ITMAX #undef EPS #undef FPMIN // ***************************************************************************** #define ITMAX 100 #define EPS 3.0e-7 void gser(double *gamser, double a, double x, double *gln) { int n; double sum,del,ap; *gln=gammln(a); if (x <= 0.0) { if (x < 0.0) { printf("*** error %s: x less than 0\n",__func__); exit(1); } *gamser=0.0; return; } else { ap=a; del=sum=1.0/a; for (n=1;n<=ITMAX;n++) { ++ap; del *= x/ap; sum += del; if (fabs(del) < fabs(sum)*EPS) { *gamser=sum*exp(-x+a*log(x)-(*gln)); return; } } printf("*** error %s: a too large, ITMAX too small\n",__func__); exit(1); } } // gser #undef ITMAX #undef EPS // ***************************************************************************** double gammq(double a, double x) { double gamser, gammcf, gln; if (x < 0.0 || a <= 0.0) { printf("*** error %s: invalid arguments\n",__func__); exit(1); } if (x < (a+1.0)) { gser(&gamser,a,x,&gln); return 1.0-gamser; } else { gcf(&gammcf,a,x,&gln); return gammcf; } } // gammq // ***************************************************************************** dds-2.4.2+ddd105/ddd/test.gib0000664000401600040160000001045711524510165013514 0ustar cbecbe{name=gib2 tricks: 1111 1111 1111 1111 1111 (max=2) } k9... jt... q...a a8...:-------------------- {name=gib3 trumps=d tricks: 2122 2121 2122 2222 1111 (max=3) } k9..2. jt...q q...a8 a8..3. {name=gib4 trumps=d tricks: 2222 2121 2222 2222 2221 (max=4) } k9..2.9 jt...q6 q...a85 a8..3.7 {name=gib5 trumps=d tricks: 3333 3232 3333 3222 2221 (max=5) } k97..2.9 jt5...q6 q...a854 a86..3.7 {name=gib10 trumps=s tricks: 7575 8777 8888 5555 8888 (max=10) } q98.2.qjt98.8 kj5.akq3..j65 t76.jt98.3.kt a42.7654.5.a2:-------8------------ {name=gin trumps=n tricks: 9998 9898 9999 6666 7777 (max=13) } T6.T92.T.AJT9532 KQ9.AQJ.96432.86 8732.753.AKQJ85. AJ54.K864.7.KQ74 {name=dbldum1 trumps=n tricks: 5454 3333 4343 5554 4444 (max=6) south can make 4/6 with W on lead 1 tricks: DT 2 tricks: CT HT S23T } T32.t.t.t aj4..q8.2 kq.98.a2. .a2.k97.a {name=dbldum2 trumps=h James Allen's trump coup and triple squeeze tricks: CCCC AAAA CCDC 99A9 A9A9 (max=13) south can make 12/13 with W on lead 0 tricks: CK S89TJQ 1 tricks: C2T D9TJQ H4 } qjt98.4.qjt9.kt2 AK76543.32.AK2.3 2.qt87.876.87654 .akj965.543.aqj9 {name=devil1 trumps=n tricks: A9A9 A9A9 7777 AAAA 9999 (max=13) south can make 9/13 with W on lead 2 tricks: DK 3 tricks: CJA D9T S56 4 tricks: H678TJQ } 65.QJT876.KT9.AJ AK83.AK.A65432.K JT92.54.Q.765432 Q74.932.J87.QT98 {name=callahan trumps=h http://users.bigpond.net.au/callahan/book1.html I came across this problem in an old, yellowed, newspaper clipping. Unfortunately no solution was included. It was promised "next week". It was introduced with: Bridge magazine in Britain has presented a double dummy problem, which is unquestionably the best ever devised. Don't despair if you cant work it out because it has defied some of the world's best players. West leads the 10 of trumps against 4 hearts. South to make 10 tricks. I am not one of the world's best players, but so far it has defied me too. tricks: 9999 8787 9999 6666 5555 (max=13) south can make 9/13 with W on lead 2 tricks: SJQA 3 tricks: S5 4 tricks: C6789 D59 H89T } AQJ5.T98.95.9876 8763.2.AQ32.AT54 T9.76.KT876.KQ32 K42.AKQJ543.J4.J {name=g410-scc trumps=s Goren on Play and Defense, p410 scissors coup tricks: 6666 9898 7676 5555 7676 (max=13) south can make 8/13 with W on lead 3 tricks: SQ 4 tricks: D89TKA H36T S4A 5 tricks: C78 } aq4.t63.akt98.87 j852.aq8.754.kq4 6.9754.qj2.t9652 kt973.kj2.63.aj3 {name=giblibno1 trumps=c tricks: 3353 6666 3333 4343 4454 (max=13) south can make 4/13 with W on lead 8 tricks: CA H248 S67 9 tricks: C29J D25Q HA } 76.A842.Q52.AJ92 K98.Q953.T87.765 AJ5.KT76.KJ63.T4 QT432.J.A94.KQ83 {name=giblibno2 trumps=c tricks: 5555 6666 3232 3333 4444 (max=13) south can make 4/13 with W on lead 9 tricks: C47QKA D35QA H8 S2JA } AJ2.8.AQ53.AKQ74 Q98743.AK.K86.95 K6.QJ6543.972.32 T5.T972.JT4.JT86 {name=bo17 trumps=c tricks: 6666 7777 5555 7787 7777 (max=13) south can make 7/13 with W on lead 5 tricks: D36Q 6 tricks: C38A H25JK S78A } A87.KJ52.Q63.A83 T42.T863.A84.762 953.AQ94.T92.QJ4 KQJ6.7.KJ75.KT95 {name=bo21 trumps=c tricks: 9797 8787 6666 A9A9 9998 (max=13) south can make 8/13 with W on lead 4 tricks: C37 D248 H348Q S36Q 5 tricks: HT } Q63.QT843.842.73 7.AJ76.KQ763.K94 AK42.K52.A9.J652 JT985.9.JT5.AQT8 {name=giblib1} JT852.93.KQ7.J82 AQ97.JT654.T6.A5 43.AK8.A542.7643 K6.Q72.J983.KQT9:88887777A9A977778888 {name=giblib2} 765.T87.Q953.K98 T4.KJ63.KT76.AJ5 KQ83.A94.J.QT432 AJ92.Q52.A842.76:AAA89998A9A9AAAA7777 {name=giblib3} 32.972.QJ6543.K6 95.K86.AK.Q98743 JT86.JT4.T972.T5 AKQ74.AQ53.8.AJ2:CCCCBBCBCCCC8888CCCC {name=giblib4} A743.JT72.Q64.QJ J5.Q63.T985.K986 62.K984.J2.T7542 KQT98.A5.AK73.A3:AAA9AAA97777BBBA8888 {name=giblib5} KQ97.63.T84.KT84 A543.AQ7.Q5.A752 J82.JT854.K92.Q3 T6.K92.AJ763.J96:99997777989899999898 {name=giblib6} QJ742.A2.QT8.Q82 AT5.63.J7632.A73 K9.KJ84.K54.J964 863.QT975.A9.KT5:55555454667666665555 {name=giblib7} 8754.QJ752.QJ83. JT.T98.AT9762.62 AKQ962.A3.5.KQT3 3.K64.K4.AJ98754:44442222333377778787 {name=giblib8} 82.AK764.A4.9432 A964.JT82.K3.AK8 QJ7.93.QT9875.J6 KT53.Q5.J62.QT75:99999999999966669999 {name=giblib9} T5.32.KJ42.AKJ52 KJ6.65.A85.QT743 A98432.AK74.93.8 Q7.QJT98.QT76.96:65653333656566665555 {name=giblib10} AK9.KQ854.QT6.74 Q83.J9.AK42.KJ63 742.T7632.J3.T85 JT65.A.9875.AQ92:878799996565AAAAAAAA dds-2.4.2+ddd105/ddd/timer.h0000664000401600040160000000710610554446617013354 0ustar cbecbe/* ************************************************************************** timer.h timer for C/C++ programs 20-Jun-2006 PMC gettimeofday() not available on MingW, changed this to pure elapsed time only, to accomodate MingW and timing problems on Windoze Copyright 2003-2006 P.M.Cronje This file is part of the Double Dummer Driver (DDD). DDD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. DDD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with DDD; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ************************************************************************** */ #ifndef TIMER_H #define TIMER_H // ----------------------------------------------------------------------------- // Timer - elapsed seconds // ----------------------------------------------------------------------------- class cTimer { public: // constructor // sets elapsed variables to 0 cTimer(); // destructor ~cTimer(); // current date/time 'dd-mon-yyyy hh:mm:ss' // static void getFormattedTime(char sztime[32]); // start() // // sets start point of variables, // sets elapsed variables to 0 // void start(); // check(...) // // if started // gets elapsed time since start() or previous check() // if not started // calls start() // // may be called any number of times after start() // void check(); // stats available only after check()/stop() // double dblElapsed() { return dElapsed;} double dblElapsed(double dmin) { return (dElapsed #include #include #include #include #include // ----------------------------------------------------------------------------- // HOW TO COMPILE AND LINK THIS WITH THE LATEST VERSION OF DDS // // The following is suggested: // // - obtain the latest dds11x.cpp and dds11x.h file for version 1.1x // of Bo Haglund's DDS and copy them into this directory // // Linux: compile and link as follows: // g++ -O2 -Wall -o ./ddd ddd.cpp dds11x.cpp defs.cpp timer.cpp giblib.cpp rng.cpp // // Windows: compile and link as follows: // g++ -O2 -Wall -o ddd.exe ddd.cpp dds11x.cpp defs.cpp timer.cpp giblib.cpp rng.cpp // // for debugging change the switch '-O2' to '-g' // // Note: on MingW you must have _WIN32 defined to compile code in timer.cpp // // ----------------------------------------------------------------------------- #include "dds11x.h" #include "giblib.h" #include "timer.h" #define szVERSION "1.05" #define szVERSION_DATE "25-Jan-2007" /* v1.03 10-Jul-2006 add set tricks to -giblib option add -tricks option v1.04 12-Jul-2006 changed giblib to C++ class cGIBLib (not struct sGIBLIb anymore) 13-jul-2006 add generateDeal(. ..) in class cGibLib 14-Jul-2006 add optional flag 'all' for option -giblib=d1-d2[-all] changes to szTricks etc. in class cGibLib 15-Jul-2006 fix 0 elapsed times for -gen 25-Jan-2007 changes to use dds11x */ // ----------------------------------------------------------------------------- // solve board status // ----------------------------------------------------------------------------- // solve board status struct sbstatus { int Code; char szCode[32]; }; #define SBSTATUS_NUM 15 #define SBSTATUS_MIN -11 #define SBSTATUS_NOFAULT 12 #define SBSTATUS_CANCELLED 2 struct sbstatus szSBStatus[SBSTATUS_NUM] = { { -11, "invalid status (less than -10)"}, { -10, "too many cards (more than 52)"}, { -9, "solutions > 3"}, { -8, "solutions < 1"}, { -7, "target > 13"}, { -6, "invalid status 6"}, { -5, "target < -1"}, { -4, "duplicate cards"}, { -3, "target > number of tricks left"}, { -2, "number of cards 0"}, { -1, "unknown fault"}, { 0, "invalid status 0"}, { 1, "no fault"}, { 2, "cancelled 2"}, { 3, "invalid status > 1"} }; // ----------------------------------------------------------------------------- // prototypes defined in this file // ----------------------------------------------------------------------------- void cleanSB(); void getSBScore(const struct futureTricks &fut, int *pmaxscore, bool bscore[14], ushort m[14][4]); bool generate(int gen, unsigned int genseed, int gencards, int gentricks); bool giblib(char *pszfile, int target, int sol, int mode, char *pszgiblib); FILE *openFile(char *pszfile); void playDD(cGIBLib *pgib, int target, int sol, int trumps, int leader); void printSBScore(int target, int solutions, struct futureTricks *pfut, double elapsed); void printSBScore(bool bscore[14], ushort m[14][4]); bool setDDS(cGIBLib *pgib, struct deal *pdl); bool testSBCode(int sbcode); bool timeAll(char *pszfile, int trumps, int leader); bool timeg(char *pszfile, int target, int sol, int mode, char *pszxcn, int leader, bool bverbose); bool tricks(cGIBLib *pgib, int ideal, int target, int sol, int mode); // ----------------------------------------------------------------------------- // macros to convert to/from DDS players/cards // ----------------------------------------------------------------------------- #define PLAYER2DDS(pl) ((pl-1)&3) #define CARD2DDS(card) (14-card) #define DDS2PLAYER(ddspl) ((ddspl+1)&3) #define DDS2CARD(ddscard) (14-ddscard) #define szGENFILE "gen.txt" // ***************************************************************************** // DDD definitions // ***************************************************************************** int main(int argc, char *argv[]) { cGIBLib gib; char *pszfile=0, *pszname=0, *pszxcn=0, *pszgiblib=0; int iarg, target=-1, solutions=3, mode=1, deal=1, trumps=-1, leader=-1; int sbcode; bool bok=false, btimeall=false, bplaydd=false, bverbose=false, btricks=false; int gen=0, gencards=52, gentricks=1; unsigned int genseed=0; FILE *fp; cTimer timer; struct deal dl; struct futureTricks fut; printf("\nDouble Dummy Driver (DDD) version %s (%s)\n", szVERSION,szVERSION_DATE); if(argc < 2) { printf( "\n" "DDD usage:\n" " ddd_executable file [opts]\n" "where:\n" " file : path for 'giblib' input file \n" "optional arguments [opts] are one or more of: \n" " -v : verbose where applicable \n" " -target=d : (default -1), see dll reference \n" " -sol=d : solution 1/2/3 (default 3), see dll reference \n" " -mode=d : 0/1 (default 1), see dll reference \n" " -trumps=t : s/h/d/c/n, this overrides the file (default=n) \n" " -leader=l : w/n/e/s, this overrides the file (default=w) \n" " but used only when no cards have been played \n" " -deal=d : 1/2/... deal number in giblib file \n" " only one of -deal or -name should be specified \n" " -name=str : deal with 'name=str' in giblib file \n" " only one of -deal or -name should be specified \n" " -playdd : play deal choosing between DDS alternatives \n" " -timeall : time all deals in file for sol=1/2/3, print stats \n" " -timeg=xcn : x - hex digit, total tricks by n-s \n" " c - contract s/h/d/c/n \n" " n - number of deals \n" " time the first n deals in the giblib file, \n" " having total tricks x at contract c, \n" " for target=-1 sol=1 mode=1 \n" " and for the specified/default leader,\n" " each deal is validated \n" " -giblib=d1-d2[-all] : validate all deals from d1 to d2 in giblib file \n" " for target=-1 sol=1 mode=1 \n" " 1. if '-all' is given, this is done for all of \n" " the 20 trick values even if some of them are '-' \n" " 2. if '-all' is not given, this is done only for \n" " those trick values which are not '-' \n" " -tricks : like -giblib, but for single deal specified \n" " by -name=str -deal=d or option \n" " generate deals: \n" " -gen=n : (required) n=number of deals to generate \n" " output is written to a file (see below) \n" " -genseed=s : (default 0) seed for random generator \n" " -gencards=c : (default=52) number of cards generated per deal,\n" " must be multiple of 4 \n" " -gentricks=t : 0,1,...,20 (default 1), number of tricks values \n" " to set randomly \n" " generate output is written to a file: \n" " gen-'genseed'-'ndeal'-'gencards'-'gentricks'.txt \n" "\n" ); return -1; } for(iarg=1; iarg 0) { generate(gen,genseed,gencards,gentricks); goto cleanup; } if(btimeall) { timeAll(pszfile,trumps,leader); goto cleanup; } else if(pszxcn) { timeg(pszfile,-1,1,1,pszxcn,(leader==-1?0:leader),bverbose); goto cleanup; } else if(pszgiblib) { giblib(pszfile,-1,1,1,pszgiblib); goto cleanup; } // open file fp = openFile(pszfile); if(fp == 0) return -1; // read giblib deal bok = gib.readFile(deal-1,pszname,fp); fclose(fp); if(!bok) { printf("%s",gib.szErrMsg); return -1; } if(btricks) { tricks(&gib,deal,-1,1,1); goto cleanup; } // if overridden from command line, set trumps/leader if(trumps != -1) gib.Trumps = trumps; if((gib.nPlayed == 0) && (leader != -1)) { // override leader/player only when no cards have been played gib.Leader = gib.Player = leader; } if(bplaydd) { playDD(&gib,target,solutions,trumps,leader); goto cleanup; } // set up dds10 if(setDDS(&gib,&dl) == false) return -1; printf("\n"); gib.print(); printf("\n"); gib.printHands(); gib.printInfo(); printf("\n"); fflush(stdout); timer.start(); InitStart(); sbcode = SolveBoard(dl,target,solutions,mode,&fut); timer.check(); if(testSBCode(sbcode) == false) exit(-1); printSBScore(target,solutions,&fut,timer.dblElapsed()); cleanup: cleanSB(); return 0; } // main // ***************************************************************************** void cleanSB() { // this is the detach code from DDS if(bestMove) free(bestMove); bestMove = 0; if(nodeCards) free(nodeCards); nodeCards = 0; if(winCards) free(winCards); winCards = 0; if(ttStore) free(ttStore); ttStore = 0; if(rel) free(rel); rel = 0; } // cleanSB // ***************************************************************************** bool generate(int gen, unsigned int genseed, int gencards, int gentricks) { // generate deals // write giblib extended format to specified file cGIBLib gib; int ntrick, sbcode, ideal, trickpos, trumps, leader; int settrick[20], setpos[20], nsettrick, itrick; int maxscore, nerror, score, ntotal; bool bscore[14]; ushort m[14][4]; FILE *fp; cTimer timer; struct deal dl; struct futureTricks fut; double elapsed, totalelapsed; unsigned long long nodes, totalnodes; char sz1[32], szfile[256]; int target=-1, sol=1, mode=1; // check arguments sprintf(szfile,"gen-%u-%d-%d-%d.txt",genseed,gen,gencards,gentricks); // if existing file, warn the user if(access(szfile,F_OK) == 0) { printf("\n*** WARNING: generate deals\n" " the file '%s' is an existing file\n" " and it may be overwritten\n" "do you want to continue? (y/n)):",szfile); fflush(stdout); char buf[80], *pch; pch = fgets(buf,255,stdin); if(pch == 0) return false; if(tolower(*pch) != 'y') return false; } if(gen < 0) { printf("*** error: gen=%d invalid number of deals to generate\n",gen); return false; } if((gencards < 4) || (gencards > 52)) { printf("*** error: gencards=%d must be >=4 and <=52\n",gencards); return false; } if((gencards % 4) != 0) { printf("*** error: gencards=%d not a multiple ofg 4\n",gencards); return false; } if((gentricks < 0) || (gentricks > 20)) { printf("*** error: gentricks=%d must be >=0 and <=20\n",gentricks); return false; } fp = fopen(szfile,"w"); if(fp == 0) { printf("*** error: %s: cannot open gen file %s for writing\n", strerror(errno),szfile); return false; } printf("\ngenerate: seed=%u deals=%d cards=%d tricks=%d file=%s\n", genseed,gen,gencards,gentricks,szfile); fflush(stdout); gib.setRNGSeed(genseed); timer.start(); nerror = ntotal = 0; elapsed = totalelapsed = 0; nodes = totalnodes = 0; for(ideal=0; ideal 0) { // initialize trick positions for(trickpos=0; trickpos<20; trickpos++) settrick[trickpos] = trickpos; nsettrick = 20; // get sorted trick positions for(itrick=0; itrickrandomUint(nsettrick); setpos[itrick] = settrick[trickpos]; if(trickpos < nsettrick-1) memmove(settrick+trickpos,settrick+trickpos+1, (nsettrick-1-trickpos)*sizeof(int)); nsettrick--; } // compute trick values for(itrick=0; itrick= 0) score = ((gib.Leader & 1) ? score: gib.numCard()/4-score); timer.check(); nodes = (unsigned long long)fut.nodes; totalnodes += nodes; elapsed = timer.dblDeltaElapsed(); printf(" deal=%d leader=%c %d%c nodes=%s elapsed=%0.2lf\n", ideal+1,chPLAYER[gib.Leader],score,(trumps==4)?'N':chSUIT[trumps], format64(nodes,sz1),elapsed); if(score < 10) gib.szTricks[trickpos] = (score + '0'); else gib.szTricks[trickpos] = (score -10 + 'A'); } } // write the deal to file fprintf(fp,"%s:%s\n",gib.szDeal,gib.szTricks); // flush file, so that cancel does not lose data fflush(fp); // print the deal printf("%d %s:%s\n",ideal+1,gib.szDeal,gib.szTricks); } timer.check(); totalelapsed = timer.dElapsed; printf("deals=%d nodes=%s elapsed=%0.2lf\n" "output written to file %s\n", gen,format64(totalnodes,sz1), totalelapsed,szfile); fclose(fp); return true; } // generate // ***************************************************************************** void getSBScore(const struct futureTricks &fut, int *pmaxscore, bool bscore[14], ushort m[14][4]) { // get DDS 'score' after SolveBoard(..) has been run int iscore, suit, alt; for(iscore=0; iscore<14; iscore++) bscore[iscore] = false; memset(m,0,14*4*sizeof(ushort)); *pmaxscore = -1; for(alt=0; alt ideal2) { printf("*** error: giblib=%s ideal1 > ideal2\n",pszgiblib); return false; } ball = false; pch = strchr(pch,'-'); if(pch) { if(strcmp(pch,"-all") != 0) { printf("*** error: giblib=%s expected '-all' after ideal2\n",pszgiblib); return false; } ball = true; } fp = openFile(pszfile); if(fp == 0) return false; printf("\n" "giblib=%s target=%d sol=%d mode=%d\n",pszgiblib,target,sol,mode); fflush(stdout); timer.start(); nerror = ntotal = 0; elapsed = totalelapsed = 0; nodes = totalnodes = 0; // skip to startdeal for(ideal=1; ideal= 0) score = ((gib.Leader & 1) ? score: gib.numCard()/4-score); nodes = (unsigned long long)fut.nodes; dealnodes += nodes; totalnodes += nodes; elapsed = timer.dblDeltaElapsed(); dealelapsed += elapsed; totalelapsed += elapsed; if(gib.szTricks[trickpos] != '-') { printf(" deal=%d leader=%c %d%c score=%d nodes=%s elapsed=%0.2lf\n", ideal,chPLAYER[gib.Leader],tricks,(trumps==4)?'N':chSUIT[trumps], score,format64(nodes,sz1),elapsed); bok = true; // test that tricks and score agree if((score < 0) || score != tricks) { nerror++; bok = false; printf(" error: deal=%d leader=%c %d%c score=%d\n", ideal,chPLAYER[gib.Leader],tricks,(trumps==4)?'N':chSUIT[trumps], score); } } else { printf(" deal=%d leader=%c %d%c nodes=%s elapsed=%0.2lf\n", ideal,chPLAYER[gib.Leader],score,(trumps==4)?'N':chSUIT[trumps], format64(nodes,sz1),elapsed); bok = false; } if(bok == false) { if(score < 10) gib.szTricks[trickpos] = (char)(score + (int)'0'); else gib.szTricks[trickpos] = (char)(score - 10 + (int)'A'); } ntotal++; } printf(" deal=%d nodes=%s elapsed=%0.2lf totalelapsed=%0.2lf\n" " ", ideal,format64(dealnodes,sz1),dealelapsed,totalelapsed); if(strlen(gib.pszName)) printf("name=%s ",gib.pszName); printf("tricks=%s (max=%d)\n", gib.szTricks,gib.numCard()/4); } printf("deals=%s nodes=%s avg=%s elapsed=%0.2lf avg=%.02lf\n", pszgiblib,format64(totalnodes,sz1), ntotal?format64(totalnodes/ntotal,sz2):format64(totalnodes,sz2), totalelapsed,ntotal?totalelapsed/(double)ntotal:totalelapsed); if(nerror) printf("*** ERROR: nerror=%d, tricks and score different\n",nerror); printf("\n"); fclose(fp); return true; } // giblib // ***************************************************************************** FILE *openFile(char *pszfile) { if(pszfile == 0) { printf("*** error: no 'giblib' file specified\n"); return 0; } if(access(pszfile,F_OK) != 0) { printf("*** error: non-existing file %s\n",pszfile); return 0; } FILE *fp = fopen(pszfile,"r"); if(fp == 0) { printf("*** error: %s: cannot open file %s for reading\n", strerror(errno),pszfile); return 0; } return fp; } // openFile // ***************************************************************************** void playDD(cGIBLib *pgib, int target, int sol, int trumps, int leader) { cTimer timer; double elapsed=0; struct deal dl; struct futureTricks fut; int sbcode, suit, card, ntotalcard; char *pch, *pchend, buf[80]; bool bhelp=false, bcompute=true; char *szplayer[4] = {"west","north","east","south"}; printf("\n"); pgib->print(); printf("\n"); timer.start(); for(;;) { pgib->printHands(); pgib->printInfo(); printf("\n"); fflush(stdout); ntotalcard = pgib->numCard(); if(ntotalcard) { // DDS only when there are cards left to play if(bcompute) { // set up dds10 if(setDDS(pgib,&dl) == false) return; timer.check(); InitStart(); sbcode = SolveBoard(dl,target,sol,1,&fut); timer.check(); if(testSBCode(sbcode) == false) exit(-1); elapsed += timer.dblDeltaElapsed(); } printSBScore(target,sol,&fut,elapsed); } if(bhelp) { printf("help for options:\n" " 'q' - quit \n" " 'h' - print this help \n" " 'u' - unplay previous card (if available) \n" " 'sc' - card/suit to play, e.g. dq/ht/s3\n" " must be valid for current player \n" ); bhelp = false; } bcompute = false; if(ntotalcard > 0) printf("enter options for %s ",szplayer[pgib->Player]); else printf("enter options "); if(ntotalcard <= 0) printf("(q/h/u): "); else if(pgib->nPlayed > 0) printf("(q/h/u/sc): "); else printf("(q/h/sc): "); fflush(stdout); pch = fgets(buf,255,stdin); if(pch == 0) continue; pchend = strchr(buf,'\n'); if(pchend) *pchend = '\0'; pchend = strchr(buf,'\r'); if(pchend) *pch = '\0'; while(*pch == ' ') pch++; if(*pch == '\0') continue; if(*pch == 'q') break; else if((pch[0] == 'h') && ((pch[1] == ' ') || (pch[1] == '\0'))) { bhelp = true; continue; } else if((pgib->nPlayed > 0) && (*pch == 'u')) { if(pgib->unplayCard()) bcompute = true; } else if(ntotalcard) { if(tolower(pch[0]) == 's') suit = 0; else if(tolower(pch[0]) == 'h') suit = 1; else if(tolower(pch[0]) == 'd') suit = 2; else if(tolower(pch[0]) == 'c') suit = 3; else continue; pch++; card = (int)cGIBLib::getCard(pch[0]); if(card == eCARD_NONE) continue; // play the card pgib->SuitPlayed[pgib->nPlayed] = suit; pgib->CardPlayed[pgib->nPlayed] = card; if(pgib->playCard(suit,card)) bcompute = true; } } } // playDD // ***************************************************************************** void printSBScore(int target, int solutions, struct futureTricks *pfut, double elapsed) { // print DDS 'score' after SolveBoard(..) has been run char sz1[32]; bool bscore[14]; ushort m[14][4]; int maxscore; printf("-- sb completed: nodes=%s tgt=%d sol=%d alt=%d elapsed=%0.2lf\n", format(pfut->nodes,sz1),target,solutions,pfut->cards,elapsed); getSBScore(*pfut,&maxscore,bscore,m); printSBScore(bscore,m); } // printSBScore // ***************************************************************************** void printSBScore(bool bscore[14], ushort m[14][4]) { int iscore, suit, nscore=0; for(iscore=0; iscore<14; iscore++) { if(bscore[iscore]) { nscore++; printf(" %2d: ",iscore); for(suit=0; suit<4; suit++) { if(m[iscore][suit]) { printf("%c ",chSUIT[suit]); while(m[iscore][suit]) { int c = leastSignificant1Bit(m[iscore][suit]); clearBit(m[iscore][suit],c); printf("%c",chCARD[c]); } printf(" "); } } printf("\n"); } } if(nscore == 0) printf(" none\n"); } // printSBScore // ***************************************************************************** bool setDDS(cGIBLib *pgib, struct deal *pdl) { // setup deal structure for DDS int pl, suit, ntrick, ntrickcard; int lastsuit, lastcard, card; pdl->trump = pgib->Trumps; // s=0,h=1,d=2,c=3,nt=4 // remaining cards from partial trick ntrick = (pgib->nPlayed / 4); ntrickcard = (pgib->nPlayed - 4 * ntrick); memset(pdl->currentTrickSuit,0,3*sizeof(int)); memset(pdl->currentTrickRank,0,3*sizeof(int)); if(ntrickcard > 0) { for(pl=0; plSuitPlayed[4*ntrick+pl]; lastcard = pgib->CardPlayed[4*ntrick+pl]; pdl->currentTrickSuit[pl] = lastsuit; pdl->currentTrickRank[pl] = CARD2DDS(lastcard); } } // DDS leader pdl->first = PLAYER2DDS(pgib->Leader); // n=0,e=1,s=2,w=3 // DDS remaining cards for(pl=0; pl<4; pl++) { int ddspl = PLAYER2DDS(pl); for(suit=0; suit<4; suit++) { ushort m=0, mp=pgib->mPlayerSuit[pl][suit]; while(mp) { card = leastSignificant1Bit(mp); clearBit(mp,card); setBit(m,CARD2DDS(card)); } pdl->remainCards[ddspl][suit] = (unsigned int)m; } } return true; } // setDDDS // ***************************************************************************** bool testSBCode(int sbcode) { // test DDS return code after SolveBoard(..) has been run if(sbcode < SBSTATUS_MIN) sbcode = SBSTATUS_MIN; else if(sbcode >= SBSTATUS_MIN+SBSTATUS_NUM) sbcode = SBSTATUS_MIN + SBSTATUS_NUM - 1; sbcode -= SBSTATUS_MIN; if(sbcode != SBSTATUS_NOFAULT) { printf("*** error: %s\n",szSBStatus[0].szCode); return false; } return true; } // testSBCode // ***************************************************************************** bool timeAll(char *pszfile, int trumps, int leader) { // run all deals in giblib file for sol=1/2/3, // collect and print the stats cGIBLib gib; int sbcode, ideal; bool bok=false; FILE *fp; cTimer timer; struct deal dl; struct futureTricks fut; double totalelapsed=0.0, elapsed[3]={0.0,0.0,0.0}; unsigned long long totalnodes=0, nodes[3]={0,0,0}; #define LEN_RESULTNAME 15 struct sResult { int nNode[3]; double Elapsed[3]; char szName[LEN_RESULTNAME+1]; }; #define MAX_RESULT 10 int sol, target=-1, mode=1, ndealalloc=0, ndeal, nresult=0; struct sResult *presult=0; for(sol=1; sol<=3; sol++) { ndeal = 0; for(;;) { // loop over deals in file // open file fp = openFile(pszfile); if(fp == 0) return false; // read giblib deal bok = gib.readFile(ndeal,0,fp); fclose(fp); if(!bok) break; if(trumps != -1) gib.Trumps = trumps; if(leader != -1) gib.Leader = leader; printf("\n"); gib.print(); printf("\n"); gib.printHands(); gib.printInfo(); printf("\n"); fflush(stdout); // set up dds10 if(setDDS(&gib,&dl) == false) return false; timer.start(); InitStart(); sbcode = SolveBoard(dl,target,sol,mode,&fut); timer.check(); if(testSBCode(sbcode) == false) return false; printSBScore(target,sol,&fut,timer.dblElapsed()); if(ndeal >= ndealalloc) { presult = (struct sResult*)realloc(presult, (ndealalloc+25)*sizeof(struct sResult)); if(presult == 0) { printf("*** error: cannot allocate result array\n"); return false; } ndealalloc += 25; } presult[ndeal].nNode[sol-1] = fut.nodes; presult[ndeal].Elapsed[sol-1] = timer.dblElapsed(); strncpy(presult[ndeal].szName,gib.pszName,LEN_RESULTNAME); presult[ndeal].szName[LEN_RESULTNAME] = '\0'; ndeal++; if(nresult < ndeal) nresult = ndeal; totalnodes += (unsigned long long)fut.nodes; nodes[sol-1] += (unsigned long long)fut.nodes; totalelapsed += timer.dblElapsed(); elapsed[sol-1] += timer.dblElapsed(); } } // print the results printf("\n" "test sol=1 sol=2 sol=3\n" "--------- ---------------- ---------------- ---------------\n" ); for(ideal=0; ideal=3\n",pszxcn); return false; } optx = pszxcn[0]; if(!isxdigit(optx)) { printf("*** error: timeg optionX=%c is not hex digit 3\n",optx); return false; } if((tolower(optx)=='e') || (tolower(optx)=='f')) { printf("*** error: timeg optionX=%c more than 13 tricks\n",optx); return false; } optx = tolower(optx); tricks = ((int)optx - (int)'0'); if((tricks < 0) || (tricks > 9)) tricks = ((int)optx - (int)'a' + 10); if(pszxcn[1] == 's') contract = 0; else if(pszxcn[1] == 'h') contract = 1; else if(pszxcn[1] == 'd') contract = 2; else if(pszxcn[1] == 'c') contract = 3; else if(pszxcn[1] == 'n') contract = 4; else { printf("*** error: timeg contract=%c is not s/h/d/c/n\n",pszxcn[1]); return false; } ndeal = atol(pszxcn+2); if(ndeal <= 0) { printf("*** error: timeg ndeal=%d is not >= 0\n",ndeal); return false; } if(contract == 4) trickpos = 0; // nt else trickpos = 4 + 4 * contract; // s/h/d/c // giblib leader goes s/e/n/w // our leader goes w/n/e/s trickpos += (3 - leader); fp = openFile(pszfile); if(fp == 0) return false; printf("\n" "timeg tricks=%d contract=%c deals=%d target=%d sol=%d mode=%d leader=%c\n", tricks,"shdcn"[contract],ndeal,target,sol,mode,chPLAYER[leader]); fflush(stdout); timer.start(); ideal = currentdeal = nerror = 0; for(;;) { // loop over deals in file // read giblib deal bok = gib.readDeal(fp); if(!bok) break; if(gib.setDeal() == false) break; currentdeal++; if(optx != tolower(gib.szTricks[trickpos])) continue; ideal++; // set up dds10 gib.Trumps = contract; if(leader != -1) gib.Leader = leader; if(setDDS(&gib,&dl) == false) return false; InitStart(); sbcode = SolveBoard(dl,target,sol,mode,&fut); timer.check(); if(testSBCode(sbcode) == false) return false; getSBScore(fut,&maxscore,bscore,m); if(maxscore < 0) { nerror++; printf("\r --- error: deal=%d ndeal=%d no score\n", currentdeal,ideal); } else { score = maxscore; if(score >= 0) //score = ((leader & 1) ? gib.numCard()/4-score : score); score = ((leader & 1) ? score: gib.numCard()/4-score); if((score < 0) || score != tricks) { nerror++; printf("\r --- error: deal=%d ndeal=%d tricks=%d score=%d\n", currentdeal,ideal,tricks,score); } } if(!bverbose) printf("\r"); printf(" deal=%d ndeal=%d nodes=%s elapsed=%0.2lf", currentdeal,ideal,format64(fut.nodes,sz1),timer.deltaElapsed); if(!bverbose) printf(" "); else printf("\n"); fflush(stdout); nodes += (unsigned long long)fut.nodes; elapsed += timer.dblDeltaElapsed(); if(minnode > fut.nodes) minnode = fut.nodes; if(maxnode < fut.nodes) maxnode = fut.nodes; if(minelapsed > timer.deltaElapsed) minelapsed = timer.deltaElapsed; if(maxelapsed < timer.deltaElapsed) maxelapsed = timer.deltaElapsed; if(ideal >= ndeal) break; } if(ideal <= 0) printf("no deals found\n"); else { printf("\rdeals=%d nodes=%s elapsed=%0.2lf \n", ndeal,format64(nodes,sz1),elapsed); printf("min_node=%s max_node=%s avg=%s\n", format(minnode,sz1),format(maxnode,sz2), format((ideal>0)?nodes/ideal:nodes,sz3)); printf("min_elapsed=%0.2lf max_elapsed=%0.2lf avg=%0.2lf\n", minelapsed,maxelapsed,(elapsed>0.0)?elapsed/(double)ideal:elapsed); } if(nerror) printf("*** ERROR: nerror=%d, incorrect maximum tricks\n",nerror); else printf("errors=0\n"); printf("\n"); fclose(fp); return true; } // timeg // ***************************************************************************** bool tricks(cGIBLib *pgib, int ideal, int target, int sol, int mode) { // run deal in giblib file for all possible tricks, // collect and print the stats int sbcode, trickpos, trumps; int maxscore, score; bool bscore[14]; ushort m[14][4]; cTimer timer; struct deal dl; struct futureTricks fut; double elapsed, dealelapsed, totalelapsed; unsigned long long nodes, dealnodes, totalnodes; char sz1[32]; if(pgib->pszName && strlen(pgib->pszName)) printf("\nname=%s",pgib->pszName); else printf("\ndeal=%d",ideal); printf(" target=%d sol=%d mode=%d\n",target,sol,mode); fflush(stdout); timer.start(); elapsed = totalelapsed = 0; nodes = totalnodes = 0; dealnodes = 0; dealelapsed = 0.0; memset(pgib->szTricks,'-',20); pgib->szTricks[20] = '\0'; for(trickpos=0; trickpos<20; trickpos++) { if(trickpos < 4) trumps = 4; else trumps = (trickpos - 4) / 4; // set up dds10 pgib->Trumps = trumps; pgib->Leader = 3 - (trickpos % 4); if(setDDS(pgib,&dl) == false) return false; InitStart(); sbcode = SolveBoard(dl,target,sol,mode,&fut); timer.check(); if(testSBCode(sbcode) == false) return false; getSBScore(fut,&maxscore,bscore,m); if(maxscore < 0) { printf("*** error: leader=%c no score\n", chPLAYER[pgib->Leader]); return false; } score = maxscore; if(score >= 0) score = ((pgib->Leader & 1) ? score: pgib->numCard()/4-score); nodes = (unsigned long long)fut.nodes; dealnodes += nodes; totalnodes += nodes; elapsed = timer.dblDeltaElapsed(); dealelapsed += elapsed; totalelapsed += elapsed; printf(" leader=%c %d%c nodes=%s elapsed=%0.2lf\n", chPLAYER[pgib->Leader],score,(trumps==4)?'N':chSUIT[trumps], format64(nodes,sz1),elapsed); if(score < 10) pgib->szTricks[trickpos] = (char)(score + (int)'0'); else pgib->szTricks[trickpos] = (char)(score - 10 + (int)'A'); } printf("nodes=%s elapsed=%0.2lf totalelapsed=%0.2lf\n", format64(dealnodes,sz1),dealelapsed,totalelapsed); printf("\n"); pgib->printHands(); printf("\n"); if(pgib->pszName && strlen(pgib->pszName)) printf("name=%s",pgib->pszName); else printf("deal=%d",ideal); printf(" tricks(leader=senw):"); for(trickpos=0; trickpos<20; trickpos++) { if((trickpos%4) == 0) { if(trickpos == 0) printf(" n="); else if(trickpos == 4) printf(" s="); else if(trickpos == 8) printf(" h="); else if(trickpos == 12) printf(" d="); else if(trickpos == 16) printf(" c="); } printf("%c",pgib->szTricks[trickpos]); } printf(" (max=%d)\n\n",pgib->numCard()/4); return true; } // tricks // ***************************************************************************** /* ================================================================================ output for: test.gib -timeall ================================================================================ test sol=1 sol=2 sol=3 --------- ---------------- ---------------- --------------- gib2 13 0.02 17 0.02 17 0.02 gib3 55 0.02 74 0.03 74 0.02 gib4 144 0.02 239 0.02 290 0.02 gib5 283 0.02 828 0.03 1,321 0.02 gib10 24,616 0.05 56,172 0.09 73,522 0.10 gin 17,372 0.05 330,860 0.37 836,869 0.96 dbldum1 1,806 0.03 3,052 0.03 3,084 0.03 dbldum2 272,365 0.25 767,339 0.71 767,339 0.69 devil1 94,935 0.12 179,691 0.21 336,969 0.34 callahan 502,044 0.60 1,303,934 1.99 1,679,319 2.33 g410-scc 121,233 0.15 140,942 0.20 464,298 0.45 giblibno1 4,026,572 5.01 6,887,233 9.50 8,470,777 11.83 giblibno2 469,241 0.48 586,377 0.61 586,377 0.60 bo17 578,078 0.69 1,342,200 1.64 1,813,889 2.06 bo21 2,614,869 3.65 3,229,875 4.45 6,668,155 9.07 giblib1 70,093 0.10 158,829 0.20 158,829 0.18 giblib2 1,362,230 1.34 1,698,895 1.68 7,052,520 6.82 giblib3 178,884 0.18 477,891 0.38 477,899 0.39 giblib4 148,267 0.16 345,545 0.35 1,523,658 1.43 giblib5 997,945 1.00 3,119,281 3.24 3,119,281 3.24 giblib6 1,634,670 1.60 3,446,862 3.70 3,805,367 3.85 giblib7 116,215 0.16 575,832 0.67 606,341 0.64 giblib8 188,369 0.20 1,115,375 1.08 1,115,375 1.06 giblib9 1,287,045 1.33 2,542,975 2.88 4,461,078 5.17 giblib10 141,894 0.41 440,351 0.49 872,148 0.91 nodes: total=88,494,703 sol-1=14,849,238 sol-2=28,750,669 sol-3=44,894,796 elapsed: total=104.43 sol-1=17.65 sol-2=34.56 sol-3=52.23 ================================================================================ output for: ../giblib -sol=1 -v -timeg=9n10 ================================================================================ timeg tricks=9 contract=n deals=10 target=-1 sol=1 mode=1 leader=W deal=4 ndeal=1 nodes=148,267 elapsed=0.17 deal=5 ndeal=2 nodes=997,945 elapsed=1.02 deal=8 ndeal=3 nodes=188,369 elapsed=0.20 deal=56 ndeal=4 nodes=2,496,093 elapsed=2.88 deal=68 ndeal=5 nodes=1,942,886 elapsed=2.07 deal=81 ndeal=6 nodes=595,946 elapsed=0.57 deal=94 ndeal=7 nodes=910,639 elapsed=1.07 deal=99 ndeal=8 nodes=2,916,346 elapsed=3.54 deal=103 ndeal=9 nodes=247,399 elapsed=0.26 deal=116 ndeal=10 nodes=353,807 elapsed=0.38 deals=10 nodes=10,797,697 elapsed=12.16 min_node=148,267 max_node=2,916,346 avg=1,079,769 min_elapsed=0.17 max_elapsed=3.54 avg=1.22 errors=0 ================================================================================ output for: ../giblib -giblib=1-1 ================================================================================ giblib=1-1 target=-1 sol=1 mode=1 deal=1 leader=S 8N score=8 nodes=76,507 elapsed=0.10 deal=1 leader=E 8N score=8 nodes=73,856 elapsed=0.10 deal=1 leader=N 8N score=8 nodes=66,062 elapsed=0.09 deal=1 leader=W 8N score=8 nodes=70,093 elapsed=0.10 deal=1 leader=S 7S score=7 nodes=633,804 elapsed=0.77 deal=1 leader=E 7S score=7 nodes=227,684 elapsed=0.26 deal=1 leader=N 7S score=7 nodes=617,829 elapsed=0.78 deal=1 leader=W 7S score=7 nodes=239,070 elapsed=0.28 deal=1 leader=S 10H score=10 nodes=44,135 elapsed=0.07 deal=1 leader=E 9H score=9 nodes=64,593 elapsed=0.10 deal=1 leader=N 10H score=10 nodes=25,802 elapsed=0.05 deal=1 leader=W 9H score=9 nodes=66,538 elapsed=0.10 deal=1 leader=S 7D score=7 nodes=710,876 elapsed=0.95 deal=1 leader=E 7D score=7 nodes=129,917 elapsed=0.17 deal=1 leader=N 7D score=7 nodes=740,822 elapsed=1.00 deal=1 leader=W 7D score=7 nodes=156,316 elapsed=0.20 deal=1 leader=S 8C score=8 nodes=287,964 elapsed=0.31 deal=1 leader=E 8C score=8 nodes=234,815 elapsed=0.26 deal=1 leader=N 8C score=8 nodes=367,526 elapsed=0.39 deal=1 leader=W 8C score=8 nodes=128,382 elapsed=0.16 deal=1 nodes=4,962,591 elapsed=6.25 totalelapsed=6.25 tricks=88887777A9A977778888 (max=13) deals=1-1 nodes=4,962,591 avg=248,129 elapsed=6.25 avg=0.31 ================================================================================ output for: test.gib -tricks -name=gin ================================================================================ name=gin target=-1 sol=1 mode=1 leader=S 9N nodes=252,521 elapsed=0.32 leader=E 9N nodes=538,589 elapsed=0.59 leader=N 9N nodes=276,076 elapsed=0.35 leader=W 8N nodes=17,372 elapsed=0.05 leader=S 9S nodes=1,268,000 elapsed=2.08 leader=E 8S nodes=1,726,949 elapsed=2.50 leader=N 9S nodes=695,799 elapsed=0.96 leader=W 8S nodes=1,656,521 elapsed=2.83 leader=S 9H nodes=476,674 elapsed=0.59 leader=E 9H nodes=531,859 elapsed=0.61 leader=N 9H nodes=437,013 elapsed=0.53 leader=W 9H nodes=298,225 elapsed=0.33 leader=S 6D nodes=474,565 elapsed=0.57 leader=E 6D nodes=238,345 elapsed=0.29 leader=N 6D nodes=370,831 elapsed=0.44 leader=W 6D nodes=60,061 elapsed=0.09 leader=S 7C nodes=1,118,923 elapsed=1.46 leader=E 7C nodes=1,074,097 elapsed=1.27 leader=N 7C nodes=1,267,293 elapsed=1.70 leader=W 7C nodes=587,523 elapsed=0.62 nodes=13,367,236 elapsed=18.18 totalelapsed=18.18 K Q 9 A Q J 9 6 4 3 2 8 6 T 6 8 7 3 2 T 9 2 7 5 3 T A K Q J 8 5 A J T 9 5 3 2 - A J 5 4 K 8 6 4 7 K Q 7 4 name=gin tricks(leader=senw): n=9998 s=9898 h=9999 d=6666 c=7777 (max=13) dds/jack database format: ------------------------- deal: A873.QJ8.T832.42 T52.965.J76.JT86 KJ96.K7.AQ.A9753 Q4.AT432.K954.KQ sol=3 contract:hearts play:W 6: D T 7: S A873 H QJ8 D 832 C 42 contract:hearts play:N 5: D J 6: S T52 H 965 D 76 C JT86 contract:hearts play:E 7: S KJ96 H K7 D AQ C A9753 contract:hearts play:S 5: D K954 6: S Q4 H AT432 C KQ db row for sol=3: A873.QJ8.T832.42 T52.965.J76.JT86 KJ96.K7.AQ.A9753 Q4.AT432.K954.KQ:H: 7777777677777666666566666677777777777776666666555566 ================================================================================ dds10x output for: test.gib -timeall ================================================================================ test sol=1 sol=2 sol=3 --------- ---------------- ---------------- --------------- gib2 13 0.02 17 0.02 17 0.02 gib3 55 0.02 74 0.02 74 0.02 gib4 132 0.02 220 0.03 267 0.02 gib5 232 0.02 677 0.02 1,091 0.03 gib10 23,990 0.05 54,710 0.09 71,783 0.10 gin 12,536 0.05 301,204 0.36 712,655 0.82 dbldum1 1,320 0.03 2,045 0.02 2,070 0.03 dbldum2 271,126 0.26 761,667 0.75 761,667 0.72 devil1 80,278 0.11 145,941 0.17 279,078 0.30 callahan 373,482 0.47 987,935 1.54 1,273,233 1.87 g410-scc 82,136 0.12 98,589 0.13 324,586 0.41 giblibno1 2,905,488 3.92 5,015,652 7.65 6,153,242 9.48 giblibno2 339,994 0.38 440,591 0.49 440,591 0.49 bo17 448,820 0.56 985,737 1.23 1,378,182 1.62 bo21 2,103,531 3.08 2,622,826 3.82 5,511,592 7.83 giblib1 39,201 0.08 97,312 0.13 97,312 0.14 giblib2 838,043 0.95 1,081,582 1.19 5,357,787 5.55 giblib3 118,210 0.12 310,481 0.28 310,487 0.28 giblib4 113,139 0.14 210,143 0.23 1,155,003 1.14 giblib5 720,826 0.77 2,301,738 2.66 2,301,738 2.60 giblib6 813,750 0.90 1,629,511 1.92 1,837,380 2.04 giblib7 89,093 0.12 443,105 0.51 469,467 0.54 giblib8 137,034 0.20 751,701 0.81 751,701 0.78 giblib9 936,282 1.05 1,734,880 2.02 3,170,680 3.77 giblib10 117,587 0.15 371,259 0.44 710,326 0.79 nodes: total=63,987,904 sol-1=10,566,298 sol-2=20,349,597 sol-3=33,072,009 elapsed: total=81.50 sol-1=13.60 sol-2=26.52 sol-3=41.38 ================================================================================ dds10x output for: ../giblib -sol=1 -v -timeg=9n10 ================================================================================ timeg tricks=9 contract=n deals=10 target=-1 sol=1 mode=1 leader=W deal=4 ndeal=1 nodes=113,139 elapsed=0.14 deal=5 ndeal=2 nodes=720,826 elapsed=0.79 deal=8 ndeal=3 nodes=137,034 elapsed=0.17 deal=56 ndeal=4 nodes=1,837,912 elapsed=2.17 deal=68 ndeal=5 nodes=1,224,530 elapsed=1.37 deal=81 ndeal=6 nodes=410,308 elapsed=0.42 deal=94 ndeal=7 nodes=593,127 elapsed=0.73 deal=99 ndeal=8 nodes=1,946,230 elapsed=2.37 deal=103 ndeal=9 nodes=155,728 elapsed=0.18 deal=116 ndeal=10 nodes=174,796 elapsed=0.22 deals=10 nodes=7,313,630 elapsed=8.57 min_node=113,139 max_node=1,946,230 avg=731,363 min_elapsed=0.14 max_elapsed=2.37 avg=0.86 errors=0 ================================================================================ dds10x output for: ../giblib -giblib=1-1 ================================================================================ giblib=1-1 target=-1 sol=1 mode=1 deal=1 leader=S 8N score=8 nodes=50,178 elapsed=0.08 deal=1 leader=E 8N score=8 nodes=39,811 elapsed=0.08 deal=1 leader=N 8N score=8 nodes=43,703 elapsed=0.08 deal=1 leader=W 8N score=8 nodes=39,201 elapsed=0.07 deal=1 leader=S 7S score=7 nodes=420,588 elapsed=0.56 deal=1 leader=E 7S score=7 nodes=155,765 elapsed=0.23 deal=1 leader=N 7S score=7 nodes=426,794 elapsed=0.60 deal=1 leader=W 7S score=7 nodes=164,092 elapsed=0.23 deal=1 leader=S 10H score=10 nodes=33,596 elapsed=0.07 deal=1 leader=E 9H score=9 nodes=45,895 elapsed=0.09 deal=1 leader=N 10H score=10 nodes=19,817 elapsed=0.05 deal=1 leader=W 9H score=9 nodes=47,289 elapsed=0.09 deal=1 leader=S 7D score=7 nodes=454,538 elapsed=0.63 deal=1 leader=E 7D score=7 nodes=80,961 elapsed=0.13 deal=1 leader=N 7D score=7 nodes=492,525 elapsed=0.69 deal=1 leader=W 7D score=7 nodes=90,791 elapsed=0.14 deal=1 leader=S 8C score=8 nodes=169,389 elapsed=0.21 deal=1 leader=E 8C score=8 nodes=144,696 elapsed=0.19 deal=1 leader=N 8C score=8 nodes=239,940 elapsed=0.29 deal=1 leader=W 8C score=8 nodes=86,347 elapsed=0.13 deal=1 nodes=3,245,916 elapsed=4.63 totalelapsed=4.63 tricks=88887777A9A977778888 (max=13) deals=1-1 nodes=3,245,916 avg=162,295 elapsed=4.63 avg=0.23 ================================================================================ dds105 output for: test.gib -timeall ================================================================================ test sol=1 sol=2 sol=3 --------- ---------------- ---------------- --------------- gib2 13 0.02 17 0.02 17 0.02 gib3 51 0.03 70 0.02 70 0.02 gib4 108 0.02 196 0.02 241 0.02 gib5 201 0.02 615 0.02 1,029 0.03 gib10 23,631 0.05 53,970 0.08 70,393 0.09 gin 11,804 0.05 264,863 0.32 639,086 0.77 dbldum1 1,190 0.02 1,756 0.02 1,781 0.03 dbldum2 244,373 0.24 691,508 0.68 691,508 0.68 devil1 77,028 0.11 140,404 0.17 269,045 0.29 callahan 342,844 0.44 918,162 1.45 1,182,747 1.72 g410-scc 77,328 0.12 92,379 0.14 316,332 0.36 giblibno1 2,211,230 3.19 3,884,687 6.13 4,797,243 7.54 giblibno2 307,453 0.36 401,005 0.47 401,005 0.47 bo17 344,725 0.44 826,074 1.08 1,184,613 1.42 bo21 1,793,723 2.60 2,249,871 3.23 4,791,239 6.78 giblib1 37,717 0.07 90,410 0.13 90,410 0.13 giblib2 780,451 0.88 1,009,229 1.15 5,027,108 5.38 giblib3 111,864 0.12 294,222 0.28 294,228 0.28 giblib4 102,296 0.13 191,583 0.22 1,086,325 1.13 giblib5 671,160 0.73 2,180,365 2.49 2,180,365 2.50 giblib6 763,607 0.85 1,531,703 1.79 1,722,183 1.98 giblib7 71,888 0.10 375,551 0.47 399,876 0.49 giblib8 120,940 0.15 689,874 0.73 689,874 0.73 giblib9 802,763 0.93 1,507,576 1.80 2,802,602 3.46 giblib10 88,779 0.13 272,940 0.34 586,850 0.69 nodes: total=55,882,367 sol-1=8,987,167 sol-2=17,669,030 sol-3=29,226,170 elapsed: total=72.11 sol-1=11.83 sol-2=23.27 sol-3=37.01 ================================================================================ dds105 output for: ../giblib -sol=1 -v -timeg=9n10 ================================================================================ timeg tricks=9 contract=n deals=10 target=-1 sol=1 mode=1 leader=W deal=4 ndeal=1 nodes=102,296 elapsed=0.14 deal=5 ndeal=2 nodes=671,160 elapsed=0.74 deal=8 ndeal=3 nodes=120,940 elapsed=0.17 deal=56 ndeal=4 nodes=1,700,168 elapsed=2.07 deal=68 ndeal=5 nodes=1,070,739 elapsed=1.26 deal=81 ndeal=6 nodes=372,940 elapsed=0.40 deal=94 ndeal=7 nodes=490,804 elapsed=0.61 deal=99 ndeal=8 nodes=1,819,501 elapsed=2.30 deal=103 ndeal=9 nodes=103,882 elapsed=0.14 deal=116 ndeal=10 nodes=150,449 elapsed=0.19 deals=10 nodes=6,602,879 elapsed=8.01 min_node=102,296 max_node=1,819,501 avg=660,287 min_elapsed=0.14 max_elapsed=2.30 avg=0.80 errors=0 ================================================================================ dds105 output for: ../giblib -giblib=1-1 ================================================================================ giblib=1-1 target=-1 sol=1 mode=1 deal=1 leader=S 8N score=8 nodes=44,008 elapsed=0.08 deal=1 leader=E 8N score=8 nodes=38,642 elapsed=0.07 deal=1 leader=N 8N score=8 nodes=36,150 elapsed=0.07 deal=1 leader=W 8N score=8 nodes=37,717 elapsed=0.07 deal=1 leader=S 7S score=7 nodes=342,376 elapsed=0.46 deal=1 leader=E 7S score=7 nodes=134,659 elapsed=0.18 deal=1 leader=N 7S score=7 nodes=358,216 elapsed=0.49 deal=1 leader=W 7S score=7 nodes=143,287 elapsed=0.20 deal=1 leader=S 10H score=10 nodes=26,798 elapsed=0.06 deal=1 leader=E 9H score=9 nodes=36,768 elapsed=0.08 deal=1 leader=N 10H score=10 nodes=16,269 elapsed=0.05 deal=1 leader=W 9H score=9 nodes=37,968 elapsed=0.08 deal=1 leader=S 7D score=7 nodes=417,861 elapsed=0.60 deal=1 leader=E 7D score=7 nodes=77,732 elapsed=0.14 deal=1 leader=N 7D score=7 nodes=448,376 elapsed=0.66 deal=1 leader=W 7D score=7 nodes=86,576 elapsed=0.15 deal=1 leader=S 8C score=8 nodes=147,551 elapsed=0.21 deal=1 leader=E 8C score=8 nodes=132,378 elapsed=0.18 deal=1 leader=N 8C score=8 nodes=212,582 elapsed=0.27 deal=1 leader=W 8C score=8 nodes=78,989 elapsed=0.13 deal=1 nodes=2,854,903 elapsed=4.23 totalelapsed=4.23 tricks=88887777A9A977778888 (max=13) deals=1-1 nodes=2,854,903 avg=142,745 elapsed=4.23 avg=0.21 ================================================================================ dds105 output for: test.gib -tricks -name=gin ================================================================================ name=gin target=-1 sol=1 mode=1 leader=S 9N nodes=217,042 elapsed=0.30 leader=E 9N nodes=490,389 elapsed=0.54 leader=N 9N nodes=242,708 elapsed=0.32 leader=W 8N nodes=12,536 elapsed=0.05 leader=S 9S nodes=1,067,876 elapsed=1.72 leader=E 8S nodes=1,423,650 elapsed=2.10 leader=N 9S nodes=579,046 elapsed=0.82 leader=W 8S nodes=1,413,760 elapsed=2.35 leader=S 9H nodes=421,052 elapsed=0.54 leader=E 9H nodes=462,996 elapsed=0.55 leader=N 9H nodes=388,427 elapsed=0.50 leader=W 9H nodes=263,960 elapsed=0.30 leader=S 6D nodes=400,416 elapsed=0.51 leader=E 6D nodes=192,319 elapsed=0.24 leader=N 6D nodes=312,717 elapsed=0.40 leader=W 6D nodes=47,573 elapsed=0.09 leader=S 7C nodes=987,365 elapsed=1.38 leader=E 7C nodes=946,439 elapsed=1.20 leader=N 7C nodes=1,102,393 elapsed=1.59 leader=W 7C nodes=487,664 elapsed=0.56 nodes=11,460,328 elapsed=16.06 totalelapsed=16.06 K Q 9 A Q J 9 6 4 3 2 8 6 T 6 8 7 3 2 T 9 2 7 5 3 T A K Q J 8 5 A J T 9 5 3 2 - A J 5 4 K 8 6 4 7 K Q 7 4 name=gin tricks(leader=senw): n=9998 s=9898 h=9999 d=6666 c=7777 (max=13) ================================================================================ dds105 output for: test.gib -tricks -name=gin ================================================================================ name=gin target=-1 sol=1 mode=1 leader=S 9N nodes=196,320 elapsed=0.27 leader=E 9N nodes=422,811 elapsed=0.49 leader=N 9N nodes=216,293 elapsed=0.29 leader=W 8N nodes=11,804 elapsed=0.05 leader=S 9S nodes=966,576 elapsed=1.68 leader=E 8S nodes=1,247,854 elapsed=2.01 leader=N 9S nodes=514,885 elapsed=0.76 leader=W 8S nodes=1,225,697 elapsed=2.09 leader=S 9H nodes=388,951 elapsed=0.52 leader=E 9H nodes=428,708 elapsed=0.55 leader=N 9H nodes=360,926 elapsed=0.48 leader=W 9H nodes=238,759 elapsed=0.28 leader=S 6D nodes=307,283 elapsed=0.41 leader=E 6D nodes=164,629 elapsed=0.22 leader=N 6D nodes=240,740 elapsed=0.32 leader=W 6D nodes=43,630 elapsed=0.08 leader=S 7C nodes=847,071 elapsed=1.21 leader=E 7C nodes=831,338 elapsed=1.09 leader=N 7C nodes=966,299 elapsed=1.45 leader=W 7C nodes=430,252 elapsed=0.51 nodes=10,050,826 elapsed=14.77 totalelapsed=14.77 K Q 9 A Q J 9 6 4 3 2 8 6 T 6 8 7 3 2 T 9 2 7 5 3 T A K Q J 8 5 A J T 9 5 3 2 - A J 5 4 K 8 6 4 7 K Q 7 4 name=gin tricks(leader=senw): n=9998 s=9898 h=9999 d=6666 c=7777 (max=13) ================================================================================ dds106 test.gib -timeal ================================================================================ test sol=1 sol=2 sol=3 --------- ---------------- ---------------- --------------- gib2 6 0.02 10 0.02 10 0.02 gib3 29 0.02 45 0.02 45 0.02 gib4 65 0.02 153 0.02 179 0.02 gib5 150 0.02 518 0.02 857 0.02 gib10 17,663 0.04 41,178 0.06 52,041 0.07 gin 8,763 0.04 224,298 0.27 581,064 0.69 dbldum1 988 0.02 1,514 0.02 1,539 0.02 dbldum2 136,602 0.15 385,323 0.41 385,323 0.42 devil1 74,661 0.10 135,218 0.15 234,862 0.24 callahan 261,312 0.33 747,439 1.13 938,208 1.33 g410-scc 45,331 0.08 57,262 0.09 237,488 0.27 giblibno1 1,744,338 2.56 3,109,979 5.08 3,888,830 6.30 giblibno2 203,773 0.25 270,424 0.31 270,424 0.32 bo17 290,006 0.35 691,275 0.85 930,229 1.07 bo21 1,502,044 2.16 1,882,400 2.66 3,926,551 5.61 giblib1 34,024 0.06 75,758 0.10 75,758 0.10 giblib2 685,093 0.73 889,056 0.93 3,631,179 3.96 giblib3 39,792 0.06 113,138 0.13 113,144 0.13 giblib4 58,370 0.08 108,555 0.12 724,213 0.74 giblib5 565,021 0.60 1,738,081 2.07 1,738,081 2.08 giblib6 631,095 0.66 1,332,592 1.48 1,502,434 1.64 giblib7 49,494 0.07 261,284 0.32 282,134 0.34 giblib8 106,018 0.12 625,995 0.66 625,995 0.66 giblib9 534,453 0.58 1,145,748 1.36 2,246,335 2.71 giblib10 28,477 0.06 91,990 0.12 371,359 0.40 nodes: total=43,705,083 sol-1=7,017,568 sol-2=13,929,233 sol-3=22,758,282 elapsed: total=56.73 sol-1=9.17 sol-2=18.39 sol-3=29.17 ================================================================================ dds106 ../exe/ddd ../giblib -sol=1 -v -timeg=9n10 ================================================================================ timeg tricks=9 contract=n deals=10 target=-1 sol=1 mode=1 leader=W deal=4 ndeal=1 nodes=58,370 elapsed=0.09 deal=5 ndeal=2 nodes=565,021 elapsed=0.61 deal=8 ndeal=3 nodes=106,018 elapsed=0.13 deal=56 ndeal=4 nodes=1,436,228 elapsed=1.74 deal=68 ndeal=5 nodes=853,171 elapsed=0.99 deal=81 ndeal=6 nodes=341,423 elapsed=0.35 deal=94 ndeal=7 nodes=450,116 elapsed=0.54 deal=99 ndeal=8 nodes=1,483,787 elapsed=1.92 deal=103 ndeal=9 nodes=92,027 elapsed=0.11 deal=116 ndeal=10 nodes=129,085 elapsed=0.16 deals=10 nodes=5,515,246 elapsed=6.65 min_node=58,370 max_node=1,483,787 avg=551,524 min_elapsed=0.09 max_elapsed=1.92 avg=0.66 errors=0 ================================================================================ dds106 ../exe/ddd ../giblib -giblib=1-1 ================================================================================ giblib=1-1 target=-1 sol=1 mode=1 deal=1 leader=S 8N score=8 nodes=32,808 elapsed=0.06 deal=1 leader=E 8N score=8 nodes=32,398 elapsed=0.06 deal=1 leader=N 8N score=8 nodes=24,961 elapsed=0.05 deal=1 leader=W 8N score=8 nodes=34,024 elapsed=0.06 deal=1 leader=S 7S score=7 nodes=286,567 elapsed=0.35 deal=1 leader=E 7S score=7 nodes=103,269 elapsed=0.13 deal=1 leader=N 7S score=7 nodes=298,877 elapsed=0.38 deal=1 leader=W 7S score=7 nodes=123,280 elapsed=0.16 deal=1 leader=S 10H score=10 nodes=23,933 elapsed=0.05 deal=1 leader=E 9H score=9 nodes=34,552 elapsed=0.06 deal=1 leader=N 10H score=10 nodes=14,916 elapsed=0.04 deal=1 leader=W 9H score=9 nodes=32,641 elapsed=0.06 deal=1 leader=S 7D score=7 nodes=348,309 elapsed=0.47 deal=1 leader=E 7D score=7 nodes=70,070 elapsed=0.10 deal=1 leader=N 7D score=7 nodes=372,832 elapsed=0.50 deal=1 leader=W 7D score=7 nodes=76,573 elapsed=0.11 deal=1 leader=S 8C score=8 nodes=124,102 elapsed=0.15 deal=1 leader=E 8C score=8 nodes=108,527 elapsed=0.13 deal=1 leader=N 8C score=8 nodes=169,251 elapsed=0.20 deal=1 leader=W 8C score=8 nodes=67,632 elapsed=0.10 deal=1 nodes=2,379,522 elapsed=3.22 totalelapsed=3.22 tricks=88887777A9A977778888 (max=13) deals=1-1 nodes=2,379,522 avg=118,976 elapsed=3.22 avg=0.16 ================================================================================ dds106 ../exe/ddd test.gib -tricks -name=gin ================================================================================ name=gin target=-1 sol=1 mode=1 leader=S 9N nodes=189,465 elapsed=0.25 leader=E 9N nodes=367,149 elapsed=0.43 leader=N 9N nodes=208,008 elapsed=0.27 leader=W 8N nodes=8,763 elapsed=0.04 leader=S 9S nodes=804,494 elapsed=1.43 leader=E 8S nodes=1,078,255 elapsed=1.69 leader=N 9S nodes=436,355 elapsed=0.64 leader=W 8S nodes=1,058,980 elapsed=1.86 leader=S 9H nodes=320,228 elapsed=0.42 leader=E 9H nodes=336,922 elapsed=0.41 leader=N 9H nodes=293,834 elapsed=0.38 leader=W 9H nodes=199,614 elapsed=0.24 leader=S 6D nodes=259,761 elapsed=0.33 leader=E 6D nodes=143,529 elapsed=0.19 leader=N 6D nodes=213,182 elapsed=0.27 leader=W 6D nodes=40,411 elapsed=0.07 leader=S 7C nodes=591,728 elapsed=0.75 leader=E 7C nodes=565,863 elapsed=0.69 leader=N 7C nodes=596,756 elapsed=0.77 leader=W 7C nodes=256,286 elapsed=0.29 nodes=7,969,583 elapsed=11.38 totalelapsed=11.38 K Q 9 A Q J 9 6 4 3 2 8 6 T 6 8 7 3 2 T 9 2 7 5 3 T A K Q J 8 5 A J T 9 5 3 2 - A J 5 4 K 8 6 4 7 K Q 7 4 name=gin tricks(leader=senw): n=9998 s=9898 h=9999 d=6666 c=7777 (max=13) ================================================================================ dds110 ./ddd test.gib -timeall ================================================================================ test sol=1 sol=2 sol=3 --------- ---------------- ---------------- --------------- gib2 6 0.02 10 0.02 10 0.02 gib3 29 0.02 45 0.02 45 0.02 gib4 65 0.02 153 0.02 179 0.02 gib5 150 0.02 518 0.02 857 0.02 gib10 17,639 0.04 41,129 0.06 51,992 0.07 gin 8,763 0.04 224,637 0.25 582,238 0.64 dbldum1 988 0.02 1,514 0.02 1,539 0.02 dbldum2 137,710 0.14 387,069 0.35 387,069 0.35 devil1 74,416 0.09 135,018 0.15 234,410 0.24 callahan 258,062 0.28 747,584 0.80 938,511 0.98 g410-scc 45,860 0.08 57,788 0.09 240,189 0.27 giblibno1 1,747,984 1.83 3,116,388 3.34 3,897,902 4.19 giblibno2 203,086 0.22 269,483 0.29 269,483 0.29 bo17 291,051 0.32 694,139 0.73 931,866 0.95 bo21 1,460,883 1.54 1,838,366 1.93 3,875,408 4.04 giblib1 34,009 0.06 75,902 0.10 75,902 0.10 giblib2 686,922 0.66 891,102 0.85 3,662,838 3.45 giblib3 39,792 0.06 113,138 0.12 113,144 0.12 giblib4 58,380 0.08 109,081 0.13 724,372 0.70 giblib5 558,633 0.56 1,741,928 1.73 1,741,928 1.73 giblib6 630,322 0.63 1,336,872 1.35 1,505,222 1.50 giblib7 49,621 0.07 261,723 0.28 282,573 0.30 giblib8 105,897 0.12 630,239 0.64 630,239 0.64 giblib9 526,845 0.53 1,146,045 1.16 2,250,098 2.30 giblib10 28,477 0.06 92,836 0.13 372,485 0.41 nodes: total=43,648,796 sol-1=6,965,590 sol-2=13,912,707 sol-3=22,770,499 elapsed: total=45.42 sol-1=7.49 sol-2=14.56 sol-3=23.37 ================================================================================ dds110 ./ddd ../giblib -sol=1 -v -timeg=9n10 ================================================================================ timeg tricks=9 contract=n deals=10 target=-1 sol=1 mode=1 leader=W deal=4 ndeal=1 nodes=58,380 elapsed=0.09 deal=5 ndeal=2 nodes=558,633 elapsed=0.56 deal=8 ndeal=3 nodes=105,897 elapsed=0.13 deal=56 ndeal=4 nodes=1,431,474 elapsed=1.46 deal=68 ndeal=5 nodes=851,777 elapsed=0.88 deal=81 ndeal=6 nodes=341,552 elapsed=0.33 deal=94 ndeal=7 nodes=449,189 elapsed=0.46 deal=99 ndeal=8 nodes=1,495,869 elapsed=1.53 deal=103 ndeal=9 nodes=92,254 elapsed=0.11 deal=116 ndeal=10 nodes=129,354 elapsed=0.16 deals=10 nodes=5,514,379 elapsed=5.71 min_node=58,380 max_node=1,495,869 avg=551,437 min_elapsed=0.09 max_elapsed=1.53 avg=0.57 errors=0 ================================================================================ dds110 ./ddd ../giblib -giblib=1-1 giblib=1-1 target=-1 sol=1 mode=1 deal=1 leader=S 8N score=8 nodes=32,808 elapsed=0.06 deal=1 leader=E 8N score=8 nodes=32,441 elapsed=0.06 deal=1 leader=N 8N score=8 nodes=25,021 elapsed=0.05 deal=1 leader=W 8N score=8 nodes=34,009 elapsed=0.06 deal=1 leader=S 7S score=7 nodes=279,639 elapsed=0.31 deal=1 leader=E 7S score=7 nodes=102,254 elapsed=0.13 deal=1 leader=N 7S score=7 nodes=301,914 elapsed=0.33 deal=1 leader=W 7S score=7 nodes=121,529 elapsed=0.14 deal=1 leader=S 10H score=10 nodes=24,004 elapsed=0.05 deal=1 leader=E 9H score=9 nodes=34,337 elapsed=0.06 deal=1 leader=N 10H score=10 nodes=14,921 elapsed=0.04 deal=1 leader=W 9H score=9 nodes=32,523 elapsed=0.06 deal=1 leader=S 7D score=7 nodes=347,634 elapsed=0.42 deal=1 leader=E 7D score=7 nodes=69,322 elapsed=0.11 deal=1 leader=N 7D score=7 nodes=371,443 elapsed=0.44 deal=1 leader=W 7D score=7 nodes=76,652 elapsed=0.11 deal=1 leader=S 8C score=8 nodes=129,621 elapsed=0.15 deal=1 leader=E 8C score=8 nodes=110,722 elapsed=0.13 deal=1 leader=N 8C score=8 nodes=172,313 elapsed=0.20 deal=1 leader=W 8C score=8 nodes=64,853 elapsed=0.09 deal=1 nodes=2,377,960 elapsed=2.99 totalelapsed=2.99 tricks=88887777A9A977778888 (max=13) deals=1-1 nodes=2,377,960 avg=118,898 elapsed=2.99 avg=0.15 ================================================================================ dds110 ./ddd test.gib -tricks -name=gin name=gin target=-1 sol=1 mode=1 leader=S 9N nodes=192,174 elapsed=0.24 leader=E 9N nodes=367,542 elapsed=0.40 leader=N 9N nodes=207,824 elapsed=0.25 leader=W 8N nodes=8,763 elapsed=0.04 leader=S 9S nodes=785,551 elapsed=0.89 leader=E 8S nodes=1,083,174 elapsed=1.24 leader=N 9S nodes=437,999 elapsed=0.50 leader=W 8S nodes=1,067,505 elapsed=1.18 leader=S 9H nodes=321,295 elapsed=0.38 leader=E 9H nodes=332,370 elapsed=0.39 leader=N 9H nodes=295,031 elapsed=0.34 leader=W 9H nodes=200,005 elapsed=0.22 leader=S 6D nodes=260,627 elapsed=0.31 leader=E 6D nodes=143,798 elapsed=0.19 leader=N 6D nodes=214,479 elapsed=0.26 leader=W 6D nodes=40,383 elapsed=0.07 leader=S 7C nodes=596,131 elapsed=0.65 leader=E 7C nodes=580,584 elapsed=0.64 leader=N 7C nodes=596,086 elapsed=0.67 leader=W 7C nodes=258,317 elapsed=0.28 nodes=7,989,638 elapsed=9.12 totalelapsed=9.12 K Q 9 A Q J 9 6 4 3 2 8 6 T 6 8 7 3 2 T 9 2 7 5 3 T A K Q J 8 5 A J T 9 5 3 2 - A J 5 4 K 8 6 4 7 K Q 7 4 name=gin tricks(leader=senw): n=9998 s=9898 h=9999 d=6666 c=7777 (max=13) ================================================================================ ddd112 ./ddd test.gib -timeall ================================================================================ test sol=1 sol=2 sol=3 --------- ---------------- ---------------- --------------- gib2 6 0.02 10 0.02 10 0.02 gib3 29 0.02 45 0.03 45 0.02 gib4 65 0.02 153 0.02 177 0.02 gib5 155 0.02 486 0.02 657 0.02 gib10 9,258 0.03 19,016 0.04 22,652 0.04 gin 6,324 0.03 219,444 0.26 475,279 0.56 dbldum1 540 0.02 1,013 0.03 1,038 0.02 dbldum2 136,598 0.15 259,032 0.25 259,032 0.25 devil1 81,548 0.10 116,045 0.14 153,721 0.18 callahan 174,145 0.21 430,962 0.49 471,674 0.54 g410-scc 43,903 0.08 44,681 0.08 112,062 0.15 giblibno1 1,163,737 1.32 1,697,850 1.98 1,788,191 2.13 giblibno2 160,340 0.20 223,954 0.27 223,954 0.27 bo17 157,301 0.19 372,446 0.43 438,133 0.49 bo21 1,795,469 2.03 1,959,809 2.25 2,407,449 2.85 giblib1 31,058 0.06 44,026 0.08 44,026 0.07 giblib2 255,255 0.28 418,134 0.53 1,931,126 2.06 giblib3 18,470 0.04 38,885 0.06 38,891 0.07 giblib4 48,509 0.07 143,359 0.17 401,817 0.45 giblib5 417,649 0.43 1,711,054 1.99 1,711,054 1.86 giblib6 560,081 0.60 937,852 1.02 996,590 1.10 giblib7 41,668 0.07 114,334 0.14 119,228 0.14 giblib8 74,780 0.10 264,695 0.29 264,695 0.29 giblib9 427,057 0.48 899,105 1.00 1,163,416 1.32 giblib10 30,338 0.06 96,455 0.14 270,423 0.33 nodes: total=28,942,468 sol-1=5,634,283 sol-2=10,012,845 sol-3=13,295,340 elapsed: total=33.59 sol-1=6.62 sol-2=11.71 sol-3=15.26 ================================================================================ ddd112 ./ddd ../giblib -sol=1 -v -timeg=9n10 ================================================================================ Double Dummy Driver (DDD) version 1.05 (25-Jan-2007) timeg tricks=9 contract=n deals=10 target=-1 sol=1 mode=1 leader=W deal=4 ndeal=1 nodes=48,509 elapsed=0.07 deal=5 ndeal=2 nodes=417,649 elapsed=0.43 deal=8 ndeal=3 nodes=74,780 elapsed=0.10 deal=56 ndeal=4 nodes=1,241,660 elapsed=1.34 deal=68 ndeal=5 nodes=319,869 elapsed=0.36 deal=81 ndeal=6 nodes=158,661 elapsed=0.18 deal=94 ndeal=7 nodes=666,682 elapsed=0.73 deal=99 ndeal=8 nodes=1,607,014 elapsed=1.79 deal=103 ndeal=9 nodes=51,985 elapsed=0.08 deal=116 ndeal=10 nodes=128,401 elapsed=0.16 deals=10 nodes=4,715,210 elapsed=5.24 min_node=48,509 max_node=1,607,014 avg=471,521 min_elapsed=0.07 max_elapsed=1.79 avg=0.52 errors=0 ================================================================================ ddd112 ./ddd ../giblib -giblib=1-1 ================================================================================ Double Dummy Driver (DDD) version 1.05 (25-Jan-2007) giblib=1-1 target=-1 sol=1 mode=1 deal=1 leader=S 8N score=8 nodes=18,322 elapsed=0.04 deal=1 leader=E 8N score=8 nodes=32,837 elapsed=0.06 deal=1 leader=N 8N score=8 nodes=10,500 elapsed=0.04 deal=1 leader=W 8N score=8 nodes=31,058 elapsed=0.06 deal=1 leader=S 7S score=7 nodes=79,659 elapsed=0.11 deal=1 leader=E 7S score=7 nodes=47,581 elapsed=0.07 deal=1 leader=N 7S score=7 nodes=52,907 elapsed=0.08 deal=1 leader=W 7S score=7 nodes=45,893 elapsed=0.07 deal=1 leader=S 10H score=10 nodes=9,517 elapsed=0.03 deal=1 leader=E 9H score=9 nodes=26,390 elapsed=0.05 deal=1 leader=N 10H score=10 nodes=6,318 elapsed=0.03 deal=1 leader=W 9H score=9 nodes=37,377 elapsed=0.07 deal=1 leader=S 7D score=7 nodes=143,865 elapsed=0.19 deal=1 leader=E 7D score=7 nodes=31,690 elapsed=0.06 deal=1 leader=N 7D score=7 nodes=139,623 elapsed=0.19 deal=1 leader=W 7D score=7 nodes=42,067 elapsed=0.07 deal=1 leader=S 8C score=8 nodes=22,516 elapsed=0.05 deal=1 leader=E 8C score=8 nodes=51,243 elapsed=0.08 deal=1 leader=N 8C score=8 nodes=13,037 elapsed=0.04 deal=1 leader=W 8C score=8 nodes=53,801 elapsed=0.08 deal=1 nodes=896,201 elapsed=1.48 totalelapsed=1.48 tricks=88887777A9A977778888 (max=13) deals=1-1 nodes=896,201 avg=44,810 elapsed=1.48 avg=0.07 ================================================================================ ./ddd test.gib -tricks -name=gin ================================================================================ Double Dummy Driver (DDD) version 1.05 (25-Jan-2007) name=gin target=-1 sol=1 mode=1 leader=S 9N nodes=204,883 elapsed=0.25 leader=E 9N nodes=341,850 elapsed=0.39 leader=N 9N nodes=202,525 elapsed=0.26 leader=W 8N nodes=6,324 elapsed=0.03 leader=S 9S nodes=404,513 elapsed=0.51 leader=E 8S nodes=880,321 elapsed=1.09 leader=N 9S nodes=481,945 elapsed=0.62 leader=W 8S nodes=679,639 elapsed=0.83 leader=S 9H nodes=317,100 elapsed=0.40 leader=E 9H nodes=230,488 elapsed=0.32 leader=N 9H nodes=341,234 elapsed=0.45 leader=W 9H nodes=53,051 elapsed=0.08 leader=S 6D nodes=420,142 elapsed=0.52 leader=E 6D nodes=111,851 elapsed=0.15 leader=N 6D nodes=448,369 elapsed=0.56 leader=W 6D nodes=37,943 elapsed=0.07 leader=S 7C nodes=460,906 elapsed=0.55 leader=E 7C nodes=276,054 elapsed=0.34 leader=N 7C nodes=515,007 elapsed=0.63 leader=W 7C nodes=297,298 elapsed=0.33 nodes=6,711,443 elapsed=8.38 totalelapsed=8.38 K Q 9 A Q J 9 6 4 3 2 8 6 T 6 8 7 3 2 T 9 2 7 5 3 T A K Q J 8 5 A J T 9 5 3 2 - A J 5 4 K 8 6 4 7 K Q 7 4 name=gin tricks(leader=senw): n=9998 s=9898 h=9999 d=6666 c=7777 (max=13) */ dds-2.4.2+ddd105/ddd/Makefile0000664000401600040160000000271311524510165013506 0ustar cbecbe# HOW TO COMPILE AND LINK THIS WITH THE LATEST VERSION OF DDS # # The following is suggested: # # - obtain the latest .cpp and dll.h file for version 1.0x # of Bo Haglund's DDS # - rename them to dds10x.cpp and dds10x.h and copy them into this directory # - change the include below to reflect the version dds10x.h # # Linux: compile and link as follows: # g++ -O2 -Wall -o ./ddd ddd.cpp dds10x.cpp defs.cpp timer.cpp giblib.cpp rng.cpp # # Windows: compile and link as follows: # g++ -O2 -Wall -o ddd.exe ddd.cpp dds10x.cpp defs.cpp timer.cpp giblib.cpp rng.cpp # # for debugging change the switch '-O2' to '-g' # # Note: on MingW you must have _WIN32 defined to compile code in timer.cpp # # Using the Makefile: # There is a Makefile supplied, edit it for the correct version of dds10x. # Run 'make' (or 'mingw32-make') to produce the executable, # note that the executable is written to ../exe/ddd. # To make the debug executable run 'make debug', # the debug executable is written to ../exe/dddd. # # The Makefile creates separate directories ../objr and ../objd for # compiled object files, apart from the directory ../exe for executables. CXX=g++ CXXFLAGS=-g -Wall -O2 LDFLAGS=-L.. LIBS=-ldds OBJ=ddd.o defs.o timer.o giblib.o rng.o PREFIX=/usr/local ddd: dds11x.h $(OBJ) g++ $(LDFLAGS) -o $@ $^ $(LIBS) dds11x.h: ln -s ../dll.h $@ install: install -d $(DESTDIR)$(PREFIX)/games install ddd $(DESTDIR)$(PREFIX)/games/dds clean: rm -f $(OBJ) ddd dds11x.h dds-2.4.2+ddd105/ddd/copying0000664000401600040160000000140410554446617013451 0ustar cbecbe Copyright 2006 P.M.Cronje This file is part of the Double Dummer Driver (DDD). DDD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. DDD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with DDD; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA dds-2.4.2+ddd105/ddd/giblib.h0000664000401600040160000002375610567641166013475 0ustar cbecbe/* ************************************************************************** giblib.h giblib reader and state for bridge C/C++ programs PM Cronje June 2006 PM Cronje 13-Jul-2006 add deal genearator Copyright 2006 P.M.Cronje This file is part of the Double Dummer Driver (DDD). DDD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. DDD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with DDD; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ************************************************************************** */ #ifndef GIBLIB_H #define GIBLIB_H #include "defs.h" #include "rng.h" #define GIBLIB_LENLINE 128 /* ============================================================================= Description ============================================================================= To read deals from a text (i.e. not a binary) giblib file. It can also be used to store the state of the deal, and to play/unplay cards starting with a given deal. The maximum line length is defined above by GIBLIB_LENLINE. Player and card values ---------------------- See the file defs.h for definitions used. Standard giblib file -------------------- The standard text giblib file consists of records like this: JT852.93.KQ7.J82 AQ97.JT654.T6.A5 43.AK8.A542.7643 K6.Q72.J983.KQT9:88887777A9A977778888 The first 67 characters is the deal, starting with the west hand, followed by north, east and south hands. The deal must consist of 52 cards. This is followed by a colon and 20 characters for possible tricks (number of tricks which can be made by north-south). Each group of four characters is for leader s/e/n/w in that order, with five groups for the contracts n/s/h/d/c in that order. Extensions ---------- This module allows a number of extensions: 1. The deal can be any number of tricks between 1 and 13 tricks, any multiple of four cards 4,8,12, ... ,48,52. 2. The possible tricks are optional. If omitted notrumps is assumed. 3. The possible tricks may be partial, e.g. 20 possible tricks are given but some of them are unknown, given by the character '-'. 4. Any number of blank lines are allowed between deals. 5. Comment lines may precede a deal. A comment starts with an open brace '{' and is terminated by a closing brace '}', spanning any number of lines. Any text can be include inside the comments, excluding the opening and closing brace characters. Options ------- Options may be imbedded in the comment. Name Option ----------- This has the form name=... followed by at least a blank or closing brace. This is used as the name for the deal, e.g. { name=gliblib1} Trumps Option ------------- This has the form trumps= followed by one of the characters s/h/d/c/n, e.g. { name=gliblib1 trumps=d} The default contract is notrump. Leader Option ------------- This has the form leader= followed by one of the characters w/n/e/s. This is the player leading the first card. In a 52-card deal it is understood that his RHO is the declarer, e.g. { name=gliblib1 trumps=n leader=e} The default leader is west. Played Option ------------- Specifies that one or more cards are to be played starting with the deal given. The leader is determined by the first card. All cards must be present in the deal, be in the hand of the right player, must follow suit, and so on. Each trick must be started by the winner of the previous trick. A card is given as two characters, the suit and the rank. Use a dash '-' to separate tricks, and a period '.' to separate cards in a trick. The following is for the first three tricks and a further three cards played from the 52-card deal given: {name=cpt leader=w played=c8.c9.ct.ck-h7.h2.hk.hj-d3.d8.dk.d5-h9.h3.ha} j95.t8632.j65.85 t862.ak54.73.q92 k743.j.a98.ajt76 aq.q97.kqt42.k43 */ // ----------------------------------------------------------------------------- class cGIBLib; // ----------------------------------------------------------------------------- class cGIBLib { public: // construct/destruct cGIBLib(); ~cGIBLib(); // print void print(); void printHands(); void printInfo(); // read deal (ideal0=0,1,2, ...) from GIBLib file bool readFile(int ideal0, char *pszname, FILE *fileptr); // read next deal in the file bool readDeal(FILE *fileptr); // play a card (it be present in current player's hand) // all variables affected are updated bool playCard(int suit, int card); // unplay previous card (there must be one or more played) bool unplayCard(); // number of cards in hand of player 0,1,2,3 (i.e. w,n,e,s) int nPlayerCard(int pl); // number of cards in all hands int numCard(); // decode szTricks[i], 0<=i<20 // if successful returns true with result in // *pleader/*ptrumps/*pntrick // if unsuccessful returns false with default result // *pleader = ePLAYER_WEST // *ptrumps = eCONTRACT_NOTRUMP // *pntrick = 0 bool getTricks(int i, int *pleader, int *ptrumps, int *pntrick); // ---------------------------------------------------------- // deal generation // ---------------------------------------------------------- // generate a random deal // this sets mPlayerSuit[4][4] only, // nothing else, // to set the giblib object, // call setGeneratedDeal(...) after this // the idea is that you may want to do filtering on the deals // checking whether a deal is acceptable first, without // having the overhead of also setting the deal into the // giblib object bool generateDeal(int ntrick); // set generated deal, // call this only after generateDeal(...), // this will set szDeal and clear szTricks with '-', // and initialize some other variables bool setGeneratedDeal(); // ---------------------------------------------------------- // READ-ONLY public data (after successful read) // ---------------------------------------------------------- // date read: deal, giblib tricks, comment, name char szDeal[68]; char szTricks[24]; char *pszComment, *pszName; // -------------------- // play/unplay // -------------------- // cards played int nPlayed; // player, suit, card for i=0,...,nPlayed-1 int PlayerPlayed[52], SuitPlayed[52], CardPlayed[52]; // trick number 0,1,... // trick card 0,1,2,3 // tricks won sofar by south/north and west/east int nTrick, nTrickCard, nTrickSN, nTrickWE; // TrickStart is index into the three lists ...Played[52] // for the first card of this trick int TrickStart; // suit led at this trick // player to this card of this trick // winning player this trick (at completion of trick) int SuitLed, Player, WinningPlayer[13]; // failed calls write their error message here, // print this to see the reason char szErrMsg[512]; // ---------------------------------------------------------- // READ-ONLY processed data (after successful read) // ---------------------------------------------------------- int Trumps; // s=0,h=1,d=2,c=3,n=4 // leader of current trick int Leader; // w=0,n=1,e=2,s=3 // bit masks of cards per player/suit: ushort mPlayerSuit[4][4]; // [player][suit] // ---------------------------------------------------------- // INTERNAL interface // ---------------------------------------------------------- char *pch, szLine[GIBLIB_LENLINE]; int nLine; bool bFileEnd; FILE *fp; static enum eCard getCard(char chcard); bool getOptions(); static char *printSuit(ushort m, char sz[]); bool readComment(); bool readLine(); void reset(); bool setDeal(); bool setPlayed(); void setName(char *pszname); bool skipComment(); // deal generator // uses RNG (random number generator) cRNG *pRNG; // set the RNG seed void setRNGSeed(unsigned int useed) { if(pRNG) pRNG->set(useed);} }; // cGIBLib // ----------------------------------------------------------------------------- #endif dds-2.4.2+ddd105/DDS_alg_descr-revE4.rtf0000664000401600040160000070771411361026142015441 0ustar cbecbe{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033\deflangfe1053{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\f2\fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f14\fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;} {\f16\froman\fcharset238\fprq2 Times New Roman CE;}{\f17\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f19\froman\fcharset161\fprq2 Times New Roman Greek;}{\f20\froman\fcharset162\fprq2 Times New Roman Tur;} {\f21\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f22\fswiss\fcharset238\fprq2 Arial CE;}{\f23\fswiss\fcharset204\fprq2 Arial Cyr;}{\f25\fswiss\fcharset161\fprq2 Arial Greek;}{\f26\fswiss\fcharset162\fprq2 Arial Tur;} {\f27\fswiss\fcharset186\fprq2 Arial Baltic;}{\f28\fmodern\fcharset238\fprq1 Courier New CE;}{\f29\fmodern\fcharset204\fprq1 Courier New Cyr;}{\f31\fmodern\fcharset161\fprq1 Courier New Greek;}{\f32\fmodern\fcharset162\fprq1 Courier New Tur;} {\f33\fmodern\fcharset186\fprq1 Courier New Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255; \red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\nowidctlpar\adjustright \lang2057 \snext0 Normal;}{ \s1\nowidctlpar\adjustright \lang2057 \sbasedon0 \snext0 heading 1;}{\s2\nowidctlpar\adjustright \lang2057 \sbasedon0 \snext0 heading 2;}{\s3\keepn\nowidctlpar\adjustright \b\lang1053 \sbasedon0 \snext0 heading 3;}{\*\cs10 \additive Default Paragraph Font;}{\*\cs15 \additive \ul\cf2 \sbasedon10 Hyperlink;}{\s16\nowidctlpar\tqc\tx4536\tqr\tx9072\adjustright \lang2057 \sbasedon0 \snext16 footer;}{\*\cs17 \additive \sbasedon10 page number;}{\*\cs18 \additive \ul\cf12 \sbasedon10 FollowedHyperlink;}}{\*\listtable{\list\listtemplateid-1\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\'01*;}{\levelnumbers;}}{\listname ;}\listid-2}{\list\listtemplateid69009423\listsimple {\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid83117072}{\list\listtemplateid69009409\listsimple{\listlevel\levelnfc23\leveljc0 \levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid402485625}{\list\listtemplateid249954820\listsimple{\listlevel\levelnfc4\leveljc0\levelfollow0 \levelstartat1\levelold\levelspace0\levelindent360{\leveltext\'02\'00);}{\levelnumbers\'01;}\f0\fbias0 }{\listname ;}\listid934823463}{\list\listtemplateid272238766{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace360\levelindent0 {\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li780\jclisttab\tx780 }{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1500\jclisttab\tx1500 } {\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\'01\u-3929 ?;}{\levelnumbers;}\f14\fbias0 \fi-360\li2220\jclisttab\tx2220 }{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace360 \levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2940\jclisttab\tx2940 }{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3660 \jclisttab\tx3660 }{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\'01\u-3929 ?;}{\levelnumbers;}\f14\fbias0 \fi-360\li4380\jclisttab\tx4380 }{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1 \levelspace360\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5100\jclisttab\tx5100 }{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5820\jclisttab\tx5820 }{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\'01\u-3929 ?;}{\levelnumbers;}\f14\fbias0 \fi-360\li6540\jclisttab\tx6540 }{\listname ;}\listid1135560398} {\list\listtemplateid988152266\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\f0\fbias0 \jclisttab\tx0 }{\listname ;}\listid1180581588}{\list\listtemplateid69009409 \listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1220364652}{\list\listtemplateid69009425\listsimple {\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00);}{\levelnumbers\'01;}\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1424648690}{\list\listtemplateid-1916079830{\listlevel\levelnfc0 \leveljc0\levelfollow0\levelstartat6\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-360\li360\jclisttab\tx360 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext \'03\'00.\'01;}{\levelnumbers\'01\'03;}\fbias0 \fi-360\li360\jclisttab\tx360 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'05\'00.\'01.\'02;}{\levelnumbers\'01\'03\'05;}\fbias0 \fi-720\li720 \jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'07\'00.\'01.\'02.\'03;}{\levelnumbers\'01\'03\'05\'07;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0 \levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'09\'00.\'01.\'02.\'03.\'04;}{\levelnumbers\'01\'03\'05\'07\'09;}\fbias0 \fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal \levelspace0\levelindent0{\leveltext\'0b\'00.\'01.\'02.\'03.\'04.\'05;}{\levelnumbers\'01\'03\'05\'07\'09\'0b;}\fbias0 \fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0 {\leveltext\'0d\'00.\'01.\'02.\'03.\'04.\'05.\'06;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d;}\fbias0 \fi-1440\li1440\jclisttab\tx1440 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext \'0f\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f;}\fbias0 \fi-1440\li1440\jclisttab\tx1440 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext \'11\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\fbias0 \fi-1800\li1800\jclisttab\tx1800 }{\listname ;}\listid1459645526}{\list\listtemplateid-144657552{\listlevel\levelnfc0\leveljc0\levelfollow0 \levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\f0\fbias0 \jclisttab\tx0 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat2\levellegal\levelspace0\levelindent0{\leveltext\'03\'00.\'01;}{\levelnumbers\'01\'03;} \fbias0 \s0\fi-360\li360\jclisttab\tx360 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'05\'00.\'01.\'02;}{\levelnumbers\'01\'03\'05;}\fbias0 \s0\fi-720\li720\jclisttab\tx720 }{\listlevel \levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'07\'00.\'01.\'02.\'03;}{\levelnumbers\'01\'03\'05\'07;}\fbias0 \s0\fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1 \levellegal\levelspace0\levelindent0{\leveltext\'09\'00.\'01.\'02.\'03.\'04;}{\levelnumbers\'01\'03\'05\'07\'09;}\fbias0 \s0\fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0 {\leveltext\'0b\'00.\'01.\'02.\'03.\'04.\'05;}{\levelnumbers\'01\'03\'05\'07\'09\'0b;}\fbias0 \s0\fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext \'0d\'00.\'01.\'02.\'03.\'04.\'05.\'06;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d;}\fbias0 \s0\fi-1440\li1440\jclisttab\tx1440 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext \'0f\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f;}\fbias0 \s0\fi-1440\li1440\jclisttab\tx1440 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext \'11\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\fbias0 \s0\fi-1800\li1800\jclisttab\tx1800 }{\listname ;}\listid1506170630}{\list\listtemplateid69009409\listsimple{\listlevel\levelnfc23\leveljc0 \levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1611858212}{\list\listtemplateid69009409\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0 \levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1686666904}{\list\listtemplateid69009409\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1 \levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1883008225}{\list\listtemplateid69009439{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0 {\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'04\'00.\'01.;}{\levelnumbers\'01\'03;}\fi-432\li792\jclisttab\tx1080 }{\listlevel \levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'06\'00.\'01.\'02.;}{\levelnumbers\'01\'03\'05;}\fi-504\li1224\jclisttab\tx1440 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0 {\leveltext\'08\'00.\'01.\'02.\'03.;}{\levelnumbers\'01\'03\'05\'07;}\fi-648\li1728\jclisttab\tx2160 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0a\'00.\'01.\'02.\'03.\'04.;}{\levelnumbers \'01\'03\'05\'07\'09;}\fi-792\li2232\jclisttab\tx2880 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0c\'00.\'01.\'02.\'03.\'04.\'05.;}{\levelnumbers\'01\'03\'05\'07\'09\'0b;}\fi-936\li2736 \jclisttab\tx3240 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0e\'00.\'01.\'02.\'03.\'04.\'05.\'06.;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d;}\fi-1080\li3240\jclisttab\tx3960 }{\listlevel\levelnfc0 \leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'10\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f;}\fi-1224\li3744\jclisttab\tx4680 }{\listlevel\levelnfc0\leveljc0\levelfollow0 \levelstartat1\levelspace0\levelindent0{\leveltext\'12\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08.;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\fi-1440\li4320\jclisttab\tx5040 }{\listname ;}\listid1938564357}{\list\listtemplateid69009409 \listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1944025331}{\list\listtemplateid69009423\listsimple {\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1968315024}}{\*\listoverridetable{\listoverride\listid83117072 \listoverridecount0\ls1}{\listoverride\listid-2\listoverridecount1{\lfolevel\listoverrideformat{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat0\levelold\levelspace0\levelindent360{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 }}\ls2} {\listoverride\listid934823463\listoverridecount0\ls3}{\listoverride\listid-2\listoverridecount1{\lfolevel\listoverrideformat{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat0\levelold\levelspace0\levelindent0{\leveltext \'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 }}\ls4}{\listoverride\listid1686666904\listoverridecount0\ls5}{\listoverride\listid1135560398\listoverridecount0\ls6}{\listoverride\listid1459645526\listoverridecount0\ls7}{\listoverride\listid1938564357 \listoverridecount0\ls8}{\listoverride\listid1968315024\listoverridecount0\ls9}{\listoverride\listid402485625\listoverridecount0\ls10}{\listoverride\listid1944025331\listoverridecount0\ls11}{\listoverride\listid1611858212\listoverridecount0\ls12} {\listoverride\listid1883008225\listoverridecount0\ls13}{\listoverride\listid1220364652\listoverridecount0\ls14}{\listoverride\listid1180581588\listoverridecount0\ls15}{\listoverride\listid1506170630\listoverridecount0\ls16}{\listoverride\listid1424648690 \listoverridecount0\ls17}}{\info{\title Bo Haglund}{\author Bo Haglund}{\operator Bo Haglund}{\creatim\yr2008\mo9\dy7\hr11\min21}{\revtim\yr2010\mo4\dy10\hr9\min55}{\version17}{\edmins115}{\nofpages23}{\nofwords6036}{\nofchars-32766}{\*\company } {\nofcharsws0}{\vern89}}\margl1417\margr1417\margt1417\margb1417 \deftab1304\widowctrl\ftnbj\aenddoc\hyphhotz425\hyphcaps0\viewkind1\viewscale100 \fet0\sectd \linex0\headery709\footery709\colsx709\sectdefaultcl {\footer \pard\plain \s16\nowidctlpar \tqc\tx4536\tqr\tx9072\pvpara\phmrg\posxr\posy0\adjustright \lang2057 {\field{\*\fldinst {\cs17 PAGE }}{\fldrslt {\cs17\lang1024 12}}}{\cs17 \par }\pard \s16\ri360\nowidctlpar\tqc\tx4536\tqr\tx9072\adjustright { \par }}{\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}} {\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8 \pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain \s1\keepn\nowidctlpar\outlinelevel0\adjustright \lang2057 {\lang1053 Bo Haglund \par }\pard\plain \nowidctlpar\adjustright \lang2057 {Rev. E4}{\lang1053 , 2010-04-09}{ \par }\pard\plain \s1\keepn\nowidctlpar\outlinelevel0\adjustright \lang2057 {\b\fs28\lang1053 \par \par Search Algorithms for a Bridge Double Dummy Solver \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\lang1053 \par This description is intended for anyone interested in the inner workings of a bridge double dummy solver (DDS). It describes my solver implemented in the Win32 environment as a DLL. \par \par }{DDS algorithm descriptions already exist, see reference list at the end. However, to my knowledge, no document exists that gives an in depth description of all algorithms covered in this document.}{\lang1053 \par \par \par \par \par {\listtext\pard\plain\b \hich\af0\dbch\af0\loch\f0 1.\tab}}\pard \nowidctlpar\jclisttab\tx0\ls16\adjustright {\b\lang1053 The basic search algorithm \par }\pard \nowidctlpar\adjustright {\lang1053 \par The search is based on the zero window search [Pearl 1980]. \par Pseudo code for its application on DD solver search is given. \par Cards searched are described as \'94moves\'94 in contrast to cards that are really played.\page \par int Search(posPoint, target, depth) \{ \par if (depth==0) \{ \par tricks=Evaluate; \par if (tricks >= target) \par value=TRUE; \par else \par value=FALSE; \par return value; \par \} \par else \{ \par GenerateMoves; \par if (player_side_to_move) \{ \par value=FALSE; moveExists=TRUE; \par while (moveExists) \{ \par Make; \par value=Search(posPoint, target, depth-1); \par Undo; \par if (value==TRUE) \par \tab goto searchExit;\tab /* Cutoff, current move recorded as \'94best move\'94 */ \par moveExists=NextMove; \par \} \par \}\tab /* Opponents to move */ \par else \{\tab \par value=TRUE; moveExists=TRUE; \par while (moveExists) \{ \par Make; \par value=Search(posPoint, target, depth-1); \par Undo; \par if (value==FALSE) \par \tab goto searchExit;\tab /* Cutoff, current move recorded as \'94best move\'94 */ \par moveExists=NextMove; \par \} \par \} \par \} \par \par searchExit: \par return value; \par \} \par \par \par }{The Search parameters are: \par {\pntext\pard\plain\f3\lang2057 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls5\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls5\adjustright {\b posPoint - }{ a pointer to a structure containing state information for the position (deal) to be searched, e.g. leading hand, hand-to-play, cards yet to play etc. \par {\pntext\pard\plain\f3\lang2057 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls5\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls5\adjustright {\b target}{ - the number of tricks the player must take. \par {\pntext\pard\plain\f3\lang2057 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls5\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls5\adjustright {\b depth}{ - the current search depth. \par }\pard \nowidctlpar\adjustright { \par Search returns TRUE if the target is reached, otherwise FALSE. \par }{\lang1053 \par When Search is called, depth is set to the number of cards left to play minus 4. \par GenerateMoves generates a list of alternative moves (=cards) that can be played in the initial position whose state da ta is pointed to by posPoint. For cards that are equivalent (e.g. AK) only the card with highest rank is generated. Card equivalence is reanalyzed after each trick. \par }{E.g. if the hand-to-play has AQ in a suit where K was played in a previous trick, then A and Q become equivalents.}{\lang1053 \par \par If the side of the player has the move, Search tries to find a move that meets the target, i.e that evaluates to TRUE. If such a move is found, search returns TRUE, and saves the move as \'94best\'94. \par If the other side has the move, Search tries to find a move that defies meeting the target, i.e. that evaluates to FALSE. If such a move is found, search returns FALSE, and saves the move as \'94best\'94. \par \par Each move in the generated move list is handled by first calling Make, which removes the ca rd from the position state information. Search is then recursively called with a position state that now has excluded the played card, depth has been decremented by one. For each new recursive call to Search, a card is removed from the position state info r mation and depth is decremented. This goes on until depth equals 0 in which case only one trick remains. The outcome of this trick is calculated by Evaluate. If the total number of tricks won by the side of the player then reaches target, Search returns T RUE, otherwise FALSE. This result propagates upwards as Search returns for each level, Undo is called which reinstalls the searched card on this level.\line Finally, Search returns for the top level. \par \par This basic search algorithm is not powerful enough to terminate the search of a typical 52 cards deal in a reasonable time. To accomplish this, a number of search algorithm enhancements are required, which will be described in the following chapters. \par \page \par The described search algorithm only tells if a predefined target can be reached. It does not tell how many tricks that the side of the player can get. This is accomplished by repeated calls to Search: \par \par g = guessed number of tricks for side of the player \par iniDepth = number of cards to play minus 4 \par upperbound = 13; \par lowerbound = 0; \par do \{ \par if (g==lowerbound) \par tricks=g+1; \par else \par tricks=g; \par if ((Search(posPoint, tricks, iniDepth)==FALSE) \{ \par upperbound=tricks-1; \par g=upperbound; \par \} \par else \{ \par lowerbound=tricks; \par g=lowerbound; \par \} \par \} \par while (lowerbound < upperbound); \par g=maximum tricks to be won by side of player.}{\b\lang1053 \par \par \par \par {\listtext\pard\plain\s3 \b \hich\af0\dbch\af0\loch\f0 2.\tab}}\pard\plain \s3\keepn\nowidctlpar\jclisttab\tx0\ls16\outlinelevel2\adjustright \b\lang1053 {Overview of the search algorithms used in the DD solver \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\b\lang1053 \par }{\lang1053 The additional functions in the pseudo code for supporting the search speed enhancements are given in }{\i\lang1053 italics}{\lang1053 . \par \page \par int Search(posPoint, target, depth) \{ \par if (no_move_yet_in_trick) \{}{\cf1\lang1053 \par }{\lang1053 }{\i\lang1053 TargetTooLowOrHigh; \par }{\lang1053 if (target_already_obtained) \par }\pard\plain \s16\nowidctlpar\adjustright \lang2057 {\lang1053 return TRUE; \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\lang1053 else if (target_can_no_longer_be_obtained) \par return FALSE;}{\i\lang1053 \par QuickTricks; \par LaterTricks; \par }{\lang1053 if (cutoff_for_player_side) \par return TRUE; \par else if (cutoff_for_opponent_side) \par return FALSE;}{\i\lang1053 \line RetrieveTTresult; \par }\pard\plain \s16\nowidctlpar\adjustright \lang2057 {\lang1053 if (transposition_table_entry_match) \{ \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\i\lang1053 }{\lang1053 if (target_reached) \par return TRUE; \par else \par return FALSE; \par \}}{\i\lang1053 \par }\pard\plain \s16\nowidctlpar\adjustright \lang2057 {\lang1053 \} \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\lang1053 \par if (depth==0) \{ \par }{\i\lang1053 evalRes=Evaluate; \par }{\lang1053 if (evalRes.tricks >= target) \par value=TRUE; \par else \par value=FALSE; \par return value; \par \} \par else \{ \par GenerateMoves; \par }{\i\lang1053 MoveOrdering; \par CheckMovesForCutoff; }{\lang1053 /* For pseudo-code, see chapter 6 */}{\i\lang1053 \par }{\lang1053 if (player_side_to_move) \{ \par value=FALSE; moveExists=TRUE; \par while (moveExists) \{ \par Make; \par value=Search(posPoint, target, depth-1);\tab \par Undo; \par if (value==TRUE) \{ \par \tab }{\i\lang1053 MergeMoveData;}{\lang1053 }{\i\lang1053 \par }{\lang1053 \tab goto searchExit;\tab /* Cutoff, current move recorded as \'94best move\'94 */ \par \} \par }{\i\lang1053 MergeAllMovesData; \par }{\lang1053 moveExists=}{\i\lang1053 NextMove}{\lang1053 ; \par \} \par \}\tab /* Opponents to move */ \par else \{\tab \par value=TRUE; moveExists=TRUE; \par while (moveExists) \{ \par Make; \par value=Search(posPoint, target, depth-1);\tab \par Undo; \par if (value==FALSE) \{ \par \tab }{\i\lang1053 MergeMoveData;}{\lang1053 \par \tab goto searchExit;\tab /* Cutoff, current move recorded as \'94best move\'94 */ \par \} \par }{\i\lang1053 MergeAllMovesData;}{\lang1053 \par moveExists=}{\i\lang1053 NextMove}{\lang1053 ; \par \} \par \} \par \} \par searchExit: \par }{\i\lang1053 AddNewTTentry; \par }{\lang1053 return value; \par \} \par \par \par }{\i\lang1053 TargetTooLowOrHigh }{\lang1053 checks the target value against the number of tricks currently won by side }{\cf1\lang1053 of the player}{\lang1053 and against number of tricks left to play. \par It is executed at the beginning of each trick, before any card has been played. \par }{If number of currently won tricks }{\cf1 by player\rquote s side}{ equals or exceeds target, Search returns TRUE.\line If number of currently won tricks }{\cf1 by player\rquote s side}{ plus tricks left to play is less than target Search returns FALSE. \par Since possible winning cards for the remaining tricks are irrelevant, no winning cards are backed up at cutoff termination.}{\lang1053 \par }\pard\plain \s16\nowidctlpar\adjustright \lang2057 {\lang1053 \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\i\lang1053 TargetTooLowOrHigh }{\lang1053 search enhancement is described e.g. in [Chang]. \par \par }\pard\plain \s1\keepn\nowidctlpar\outlinelevel0\adjustright \lang2057 {\i QuickTricks}{ determines if the side to move can take one or more sure tricks. }{\lang1053 E.g. if the hand to move has an Ace in an NT contract, at least one sure trick can be taken. \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\lang1053 It is executed at the beginning of each trick, before any card has been played. A simple quick trick is also executed after the leading card of the trick is played.}{ \par }\pard\plain \s1\keepn\nowidctlpar\outlinelevel0\adjustright \lang2057 {\lang1053 Assuming that the sure tricks are won by the side to move, then the conditions for search cutoff in }{\i\lang1053 TargetTooLowOrHigh}{\lang1053 are again tested to produce further search cutoffs. \par The detailed conditions for determination of sure tricks are described in Chapter 3. \par }\pard\plain \nowidctlpar\adjustright \lang2057 {When quicktricks win by rank, they are backed up at cutoff termination. \par }\pard\plain \s1\keepn\nowidctlpar\outlinelevel0\adjustright \lang2057 {\lang1053 \par The idea of }{\i\lang1053 QuickTricks }{\lang1053 is described e.g. in [Chang]. \par }\pard\plain \nowidctlpar\adjustright \lang2057 { \par }{\i LaterTricks}{ determines if the opponents of the side to move can take one or more tricks at their turn or later in the play. It is also executed at the beginning of each trick and uses similar criteria for search cutoff as }{\i Quicktricks}{. \par When quicktricks win by rank, they are backed up at cutoff termination.\line For a detailed description, see Chapter 4. \par }\pard\plain \s1\keepn\nowidctlpar\outlinelevel0\adjustright \lang2057 {\lang1053 \par }{\i\lang1053 RetrieveTTresult }{\lang1053 scans the set of positions in the transposition table to see if there is a match against the current position. \par It is executed at the beginning of each trick, before any card has been played. After detection of a transposition table entry match, the winning ranks necessary in the remaining cards are backed up. \line For details, see Chapter 7. \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\fs20\lang1053 \par }{\i Evaluate }{returns evalResult which updates the position state information. evalResult contains: \par {\listtext\pard\plain\f3\lang2057 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li780\nowidctlpar\jclisttab\tx780\ls6\adjustright {\b evalResult.tricks}{, the number of tricks won by the side of the player, and \par {\listtext\pard\plain\f3\lang2057 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}{\b evalResult.winRank}{ which includes the card in the last trick that won by rank. \par }\pard \nowidctlpar\adjustright {E.g. if the last trick includes the spades A, Q, 9 and 3, evalResult.winRank returns spade A. But \par if the last trick was won without a win by rank as for spade 5 (leading and winning card), heart A, heart Q, heart 5, no winning rank is returned. }{\lang1053 \par \par }{Keeping record of cards that win by ranks and subsequently using this information to ignore ranks for other cards is discussed in the Partition Search concept invented by Matthew Ginsberg and described in his paper [Ginsberg]. }{\lang1053 \par \par }{\i MoveOrdering. }{The alternative cards created by MoveGenerate are sorted, with the cards most likely to terminate the search fastest being sorted first in the move list.The allocation of card weights are described in detail in Chapter 5.}{\lang1053 \par \par }{\i\lang1053 CheckMovesForCutoff }{\lang1053 checks if any of the moves just generated will lead to a position that can be found in the transposition table. If so, an immediate S earch return can be done, saving unnecessary search effort. This is further described in Chapter 6. \par \par To my knowledge this is not described anywhere for usage in a DDS. It is described in [Plaat et al.] and named Enhanced Transposition Cutoffs. \par \par At move search cutoff,}{\i\lang1053 MergeMoveData }{\lang1053 collects the union of the backed up accumulated winning ranks and the rank of the made move, assuming it did win by rank. The state data of the position is updated with the collected information. \par \par }{\i\lang1053 MergeAllMovesData }{\lang1053 collects the un ion of the backed up accumulated winning ranks, the previous accumulated winning ranks of the alternative moves generated on this depth, and the rank of the made move, assuming it did win by rank. When all alternative moves have been searched without a cu toff, the state data of the position is updated with the collected information. \par \par The information from }{\i\lang1053 MergeMoveData}{\lang1053 and }{\i\lang1053 MergeAllMovesData}{\lang1053 is later stored in the transposition table and determines which ranks that are essential when }{\i\lang1053 RetrieveTTresult}{\lang1053 scans th e set of positions in the transposition table. A match of ranks with the current position is only needed for winning ranks. See Chapter 7.}{\strike\cf6\lang1053 \par }{\lang1053 \par }{\i\lang1053 AddNewTTentry }{\lang1053 adds the evaluated position as a new entry in the transposition table. See Chapter 7. \par \par }{\i\lang1053 NextMove }{\lang1053 filters out all \'94small\'94 cards except one per hand/suit combination. A \'94small\'94 card is a backed up card that is shown to never win by rank. The rest of the \'94small\'94 card moves for the hand/suit combination are never searched, leading to a smaller search tree.\line This search enhancement was suggested by Hans Kuijf [Kuijf]. \par \par \par \par {\listtext\pard\plain\b \hich\af0\dbch\af0\loch\f0 3.\tab}}\pard \nowidctlpar\jclisttab\tx0\ls16\adjustright {\b\lang1053 The Quick Tricks cutoff algorithm \par }\pard \nowidctlpar\adjustright {\b\lang1053 \par }{\lang1053 The number of tricks that can immediately be taken by the side to play the leading card of the trick consists of: \par {\pntext\pard\plain\hich\af0\dbch\af0\loch\f0 a)\tab}}\pard \fi-360\li360\nowidctlpar\tx360{\*\pn \pnlvlbody\ilvl0\ls3\pnrnot0\pnlcltr\pnstart1\pnindent360 {\pntxta )}}\ls3\adjustright {\lang1053 The number of tricks that can be taken by the hand-to-play, and \par {\pntext\pard\plain\hich\af0\dbch\af0\loch\f0 b)\tab}}\pard \fi-360\li360\nowidctlpar\tx360{\*\pn \pnlvlbody\ilvl0\ls3\pnrnot0\pnlcltr\pnstart1\pnindent360 {\pntxta )}}\ls3\adjustright {\lang1053 The number of tricks that can be taken by the partner of the hand-to-play \par }\pard \nowidctlpar\adjustright {\lang1053 At return by }{\i\lang1053 QuickTricks}{\lang1053 , the position state information is updated with the winning ranks found. \par \par }{Of course, in order to add b), there must be an entry from the hand-to-play to the partner\rquote s hand. \par \par For each \'94s\'94 (suit) the following is calculated:}{\lang1053 \par \par If the hand-to-play is the only hand having cards in s, and the opponents have no trumps (when s is not trumps), the number of quick tricks for s is the suit length of the hand-to-play. \par \par If the opponents have no trumps, a check is made to see if quick tricks equal to the maximum of the trumps length for leading hand and the partner causes a search cutoff. \par \par If the hand-to-play has a card in a suit where the partner has a winning rank, and partner is the only hand having cards in s: \par The number of quick tricks for s is the suit length of partner. \par \par Else: \par If the winning rank is in hand-to-play, and the opponents can not ruff, the number of quick tricks is incremented by one. Further, if the second best rank is also in hand-to-play, and the opponents cannot still ruff, the quick tricks is again incremented by one. \par \par Else: \par If the winning rank is in partner and partner has winning rank as entry, the same applies for the partner as for the hand-to-play described above. \par \par }{If it is a trump contract, the first suit to be investigated is the trump suit. Then if there are trump suit quick tricks for the side to play, those are cashed and quick tricks incremented accordingly. \par \line When the other suits are investigated for quick tricks, only the remaining opponent trump cards need to be considered.\line }{\lang1053 \par }{The quick tricks are then summarized from each suit, and the total calculated}{\lang1053 . \par \par A simple Quick Tricks algorithm is also executed after the leading card of the trick has been played: \par \par A quick trick is gained either if the hand-to-play or the partner can win the current trick with the card having the highest rank of the suit played, or if hand-to-play or the partner can win the trick by ruffing. \par \par The idea to also execute Quick Tricks after the leading card has been played was given by Hans Kuijf [Kuijf]. \par \par \par \par {\listtext\pard\plain\b \hich\af0\dbch\af0\loch\f0 4.\tab}}\pard \nowidctlpar\jclisttab\tx0\ls16\adjustright {\b\lang1053 The Later Tricks cutoff algorithm}{\lang1053 \par }\pard \nowidctlpar\adjustright {\lang1053 \par Check for search cutoff if the opponents to the trick leading hand have at least a sure trick later. \par \par }{\b\lang1053 If not trump contract:\line \par {\pntext\pard\plain\hich\af0\dbch\af0\loch\f0 1)\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlbody\ilvl0\ls17\pnrnot0\pndec\pnstart1\pnindent360\pnhang{\pntxta )}}\ls17\adjustright {\lang1053 The opponents have at least a sure trick if for all suits where the trick leading hand has a card, the side of the leading hand does not have the highest rank.\line More than one sure trick can be taken by the opponents if they possess the winning rank for more than one suit, or\line \par {\pntext\pard\plain\hich\af0\dbch\af0\loch\f0 2)\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlbody\ilvl0\ls17\pnrnot0\pndec\pnstart1\pnindent360\pnhang{\pntxta )}}\ls17\adjustright {\lang1053 Assume that all suits where the side of the trick leading hand has the winning rank give maximum possible number of tricks, i.e. that the sure trick number is the sum of the\line maximum lengths of these suits.\line If this still cannot cause a cutoff for the trick leading side, allocate one sure trick for the opponents side. \par }\pard \nowidctlpar\adjustright {\lang1053 \par }{\b\lang1053 If trump contract: \par }{\lang1053 \par Quick tricks for the opponents of the leading hand are added when the opponents have one or more winning trumps. This idea was given by Pedja Stanojevic [Stanojevic].\line \line 1) If the opponent side have all the trumps, the number of sure tricks is the maximum suit length\line length, or\line \par 2) If the opponent side has the highest trump, they have 1 sure trick. If they also have the second\line highest trump, they have 2 sure tricks, or\line \line 3) If the opponent side has the second highest trump plus at least one tr ump more behind the \line hand with the highest trump, the opponent side has 1 sure trick. \par \page \par {\listtext\pard\plain\s3 \b \hich\af0\dbch\af0\loch\f0 5.\tab}}\pard\plain \s3\keepn\nowidctlpar\jclisttab\tx0\ls16\outlinelevel2\adjustright \b\lang1053 {The Move Ordering algorithm \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\b\lang1053 \par }{\lang1053 The weight of a card in the move list is affected by the suit and the rank of the card and by the other cards in the same trick. \par The weights of the cards in the move list are used to sort them, }{with the cards having the highest weight being sorted first in the list}{\lang1053 . \par \par If the hand-to-play is trick leading hand or void in the suit played by leading hand, the card with the highest weight for each present suit will get a high additional bonus weight. After list resorting, those cards will occupy the first positions in the move list. \par \par Two "best moves" are maintained for each searched depth, one for an alpha-beta cutoff and one at a Transpos ition Table entry match. At an alpha-beta cutoff, the move causing the cutoff overwrites the present "best move" for the current depth. When a Transposition Table entry is created, the current best move is stored in that entry if: \par The target is met and the leading hand belongs to the player\rquote s side, or target is not met and the leading hand belongs to the other side. Otherwise the best move is not stored in the Transposition Table entry. \par At a Transposition Table entry match, }{its stored best move will be best move for the current search depth.}{\lang1053 \par \par By \'94card move\'94 in the following pseudo code is meant the card by the hand-to-play that is getting a weight in the move list. }{\cf1\lang1053 The \'94card rank\'94 is a value in the range 2-14, corresponding to the card ranks 2 to the Ace. \par \par }{\lang1053 For the determination of the weight, it is calculated whether or not the current card move is a card that wins the current trick for the side of the hand-to-play, assuming that both sides play their optimum cards. \par \par If the hand-to-play is void in the trick lead suit, the suit selected for the discard gets the following\line bonus: \par \par suitAdd = ((suit length) * 64)/36; \par \par If the suit length is 2, and the hand-to-play has the next highest rank of the suit, the bonus \line (suitAdd) is subtracted by 2. }{\cf1\lang1053 \par }{\fs20\lang1053 \par \par }\pard\plain \s2\keepn\nowidctlpar\outlinelevel1\adjustright \lang2057 {\ul\lang1053 Hand-to-play is trick leading hand \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\lang1053 \par The contribution of the suit to the weight: \par \par }\pard\plain \s16\nowidctlpar\adjustright \lang2057 {\lang1053 suitWeightDelta = suitBonus \endash ((countLH+countRH) * 32)/15 \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\lang1053 \par suitBonus has the initial value 0, changed if conditions below apply: \par \par If trump contract, and the suit is not trump, then there is a (negative) suitBonus change of \endash 10 if \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\nowidctlpar\tx360{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnindent360 {\pntxtb \'b7}}\ls2\adjustright {\lang1053 LHO is void and LHO has trump card(s), or \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\nowidctlpar\tx360{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnindent360 {\pntxtb \'b7}}\ls2\adjustright {\lang1053 RHO is void and RHO has trump card(s) \par }\pard \nowidctlpar\tx360\adjustright {\lang1053 \line If RHO has either the highest rank of the suit played by hand-to-play or the next highest rank, \par then there is a suitBonus change of \endash 18. \par \par If it is a trump contract, the suit is not trump, own hand has a singleton, own hand has at least one trump, partner has the highest rank in the suit and at least a suit length of 2, then there is a suitBonus change of +16. \par }\pard \nowidctlpar\adjustright {\lang1053 \par countLH = (suit length of LHO) * 4, if LHO is not void in the suit, \par countLH = (depth + 4), if LHO is void in the suit \par \par countRH = (suit length of RHO) * 4, if RHO is not void in the suit, \par countRH = (depth + 4), if RHO is void in the suit \par \par Suits are thus favoured where the opponents have as few move alternatives as possible. \par \par \par if (trick winning card move) \{ \par if (one of the opponents has a singleton highest rank in the suit) \par weight = suitWeightDelta + 40 \endash (rank of card move) \par else if (hand-to-play has highest rank in suit) \{ \par if (partner has second highest rank in suit) \par weight = suitWeightDelta + 50 \endash (rank of card move) \par else if (the card move is the card with highest rank in the suit) \par weight = suitWeightDelta + 31 \par else \par weight = suitWeightDelta + 19 \endash (rank of card move) \par \} \par else if (partner has highest rank in suit) \{ \par if (hand-to-play has second highest rank in suit) \par weight = suitWeightDelta + 50 \endash (rank of card move) \par else \par weight = suitWeightDelta + 35 \endash (rank of card move) \par \} \par else if (hand-to-play has second highest rank together with equivalent card(s) in suit) \par weight = suitWeightDelta + 40 \par else \par weight = suitWeightDelta + 30 \endash (rank of card move) \par if (the card move is \'94best move\'94 as obtained at alpha-beta cutoff) \par weight = weight + 52; \par if (the card move is \'94best move\'94 as obtained from a Transposition Table entry match) \par weight = weight + 11; \par \} \par else \{\tab /* Not a trick winning move */ \par if (either LHO or RHO has singleton in suit which has highest rank) \par weight = suitWeightDelta + 29 \endash (rank of card move) \par else if (hand-to-play has highest rank in suit) \{ \par if (partner has second highest rank in suit) \par weight = suitWeightDelta + 44 \endash (rank of card move) \par else if (the card move is the card with highest rank in the suit) \par weight = suitWeightDelta + 25 \par else \par weight = suitWeightDelta + 13 \endash (rank of card move) \par \} \par else if (partner has highest rank in suit) \{ \par if (hand-to-play has second highest rank in suit) \par weight = suitWeightDelta + 44 \endash (rank of card move) \par else \par weight = suitWeightDelta + 29 \endash (rank of card move) \par \} \par else if (hand-to-play has second highest rank together with equivalent card(s) in suit) \par weight = suitWeightDelta + 29 \par else \par weight = suitWeightDelta + 13 \endash (rank of card move) \par if (the card move is \'94best move\'94 as obtained at alpha-beta cutoff) \par weight = weight + 20; \par if (the card move is \'94best move\'94 as obtained from a Transposition Table entry match) \par weight = weight + 9; \par \} \par \par \par }{\ul\lang1053 Hand-to-play is left hand opponent (LHO) to leading hand \par }{\lang1053 \par if (trick winning card move) \{ \par if (hand-to-play void in the suit played by the leading hand) \{ \par if (trump contract and trump is equal to card move suit) \par }{\cf1\lang1053 weight = 30 - (rank of card move) + suitAdd \par else \par weight = 60 - (rank of card move) + suitAdd \par \} \par else if (lowest card for partner to leading hand is higher than LHO played card) \par weight = 45 - (rank of card move) \par else if (RHO has a card in the leading suit that is higher than the trick leading card\line but lower than the highest rank of the leading hand) \par weight = 60 - (rank of card move) \par else if (LHO played card is higher than card played by the leading hand) \{ \par if (played card by LHO is lower than any card for RHO in the same suit) \par weight = 75 - (rank of card move) \par else if (played card by LHO is higher than any card in the same suit for the leading hand) \par weight = 70 - (rank of card move) \par else \{ \par }{\lang1053 if (LHO move card has at least one equivalent card) \{ \par }{\cf1\lang1053 weight = 60 - (rank of card move)}{\lang1053 \par else \par }{\cf1\lang1053 weight = 45 - (rank of card move) \par \} \par \} \par else if (RHO is not void in the suit played by the leading hand) \{ \par }{\lang1053 if (LHO move card has at least one equivalent card) }{\cf1\lang1053 }{\lang1053 }{\cf1\lang1053 \par weight = 50 - (rank of card move) \par else \par weight = 45 - (rank of card move) \par \} \par else \par weight = 45 - (rank of card move) \par \} \par else \{\tab /* card move is not trick winning */ \par }{\lang1053 if (hand-to-play void in the suit played by the leading hand) \{ \par if (trump contract and trump is equal to card move suit)}{\cf1\lang1053 \par }{\lang1053 }{\cf1\lang1053 weight = 15 - (rank of card move) + suitAdd \par else \par weight = - (rank of card move) + suitAdd \par \} \par else if (lowest card for partner to leading hand or for RHO in the suit played is higher \line than played card for LHO) \par weight = - (rank of card move) \par else if (LHO played card is higher than card played by the leading hand) \{ \par }{\lang1053 if (LHO move card has at least one equivalent card) \par }{\cf1\lang1053 weight = 20 - (rank of card move) \par else}{\lang1053 \par }{\cf1\lang1053 weight = 10 - (rank of card move) \par \} }{\lang1053 \par else \par }{\cf1\lang1053 weight = - (rank of card move) \par \} }{\lang1053 }{\cf1\lang1053 }{\lang1053 }{\cf1\lang1053 \par }{\lang1053 \par \par \par }\pard\plain \s2\keepn\nowidctlpar\outlinelevel1\adjustright \lang2057 {\ul\lang1053 Hand-to-play is partner to trick leading hand \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\lang1053 \par if (trick winning card move) \{ \par if (hand-to-play void in the suit played by the leading hand) \{ \par if (card played by the leading hand is highest so far) \{ \par if (card by hand-to-play is trump and the suit played by the leading hand is not trump) \par }{\cf1\lang1053 weight = 30 - (rank of card move) + suitAdd \par else \par weight = 60 - (rank of card move) + suitAdd \par \} \par else if (hand-to-play is on top by ruffing) \par weight = 70 - (rank of card move) + suitAdd \par else if (hand-to-play discards a trump but still loses) \par weight = 15 - (rank of card move) + suitAdd \par else }{\lang1053 \par }{\cf1\lang1053 weight = 30 - (rank of card move) + suitAdd \par \} \par else }{\lang1053 \par }{\cf1\lang1053 weight = 60 - (rank of card move) \par \} \par else \{ /* card move is not trick winning */ \par }{\lang1053 if (hand-to-play void in the suit played by the leading hand) \{ \par }{\cf1\lang1053 if (hand-to-play is on top by ruffing) \par weight = 40 - (rank of card move) + suitAdd \par else if (hand-to-play underruffs */ \par weight = -15 - (rank of card move) + suitAdd \par else \par weight = - (rank of card move) + suitAdd \par \} \par else \{ \par if (the card by hand-to-play is highest so far) \{ \par if (rank of played card is second highest in the suit) \par weight = 25 \par else }{\lang1053 if (hand-to-play card has at least one equivalent card) \par }{\cf1\lang1053 weight = 20 - (rank of card move) \par else \par weight = 10 - (rank of card move) \par \} \par else \par weight = -10 - (rank of card move) \par \} \par \}}{\lang1053 \par \par }{\ul\lang1053 Hand-to-play is right hand opponent (RHO) to leading hand \par \par }{\lang1053 if (hand-to-play is void in leading suit) \{ \par if (LHO has current highest rank of the trick) \{ \par if (card move ruffs) \par weight = 14- (rank of card move) + suitAdd \par else \par weight = 30- (rank of card move) + suitAdd \par }{\fs20\lang1053 \} \par }{\lang1053 else if (hand-to-play ruffs and wins) \par }{\fs20\lang1053 }{\lang1053 weight = 30- (rank of card move) + suitAdd \par else if (card move suit is trump, but not winning) \par weight = - (rank of card move) \par else \par weight = 14- (rank of card move) + suitAdd \par \} \par else if (LHO has current winning move) \{ \par if (RHO ruffs LHO\rquote s winner) \par weight = 24 - (rank of card move) \par else \par weight = 30- (rank of card move) \par \} \par else if (card move superior to present winning move not by LHO) \{ }{\fs20\lang1053 \par }{\lang1053 weight = 30- (rank of card move) \par else \{ \par if (card move ruffs but still losing) \par weight = - (rank of card move) \par else \par weight = 14- (rank of card move) \par \}}{\fs20\lang1053 \par }{\lang1053 \par }\pard \fi1304\nowidctlpar\adjustright {\lang1053 \par \page \par {\listtext\pard\plain\b \hich\af0\dbch\af0\loch\f0 6.\tab}}\pard \nowidctlpar\jclisttab\tx0\ls16\adjustright {\b\lang1053 Algorithm to try early cutoff for generated moves \par }\pard \nowidctlpar\adjustright {\b\lang1053 \par }\pard\plain \s1\keepn\nowidctlpar\outlinelevel0\adjustright \lang2057 {\lang1053 After generating moves at the end of a trick, they are each checked to see if one of them will lead to a position that already is stored in the Transposition Table. \par Due to the processing overhead, this check is only made if the depth is 33 or more (i.e there are at least 33 cards in the position). \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\lang1053 Pseudo code: \par }\pard\plain \s1\keepn\nowidctlpar\outlinelevel0\adjustright \lang2057 {\lang1053 \par moveExists = TRUE; \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\lang1053 while (moveExists) \{ \par Make; \par depth = depth \endash 1; \par RetrieveTTresult; \par if (hit in the transposition table) \{ \par Search returnsTRUE if value of the position is TRUE and player side to move, or \par FALSE if value of the position is FALSE and opponents side to move. \par Else: Increment weight of move with 100. \par \} \par depth = depth +1; \par Undo; \par moveExists = NextMove; \par \} \par \par The performance improvement for this enhancement is less than for the other enhancements. The number of generated nodes is roughly decreased by 10% and the search time is slighly decreased. \par \par \par \par {\listtext\pard\plain\b \hich\af0\dbch\af0\loch\f0 7.\tab}}\pard \nowidctlpar\jclisttab\tx0\ls16\adjustright {\b\lang1053 Storage and retrieval of position state data in the Transposition Table \par }\pard\plain \s16\nowidctlpar\tx360\adjustright \lang2057 {\lang1053 }{\b\lang1053 \line }{\cf1\lang1053 Positions stored in the Transposition Table always consist of completed tricks. Positions stored start at depth=4, then 8,12, and so on. The information stored is information on won cards, th e suit lengths of the hands, the hand to play the leading card in the position and upper and lower bounds for the number of future tricks to be taken by the side of the player. \par \par Starting from issue 1.1.8, each \'94winning cards node\'94 contain all winning cards for one suit after an idea by Jo\'ebl Bradmetz. This new solution is faster.}{\b\cf1 \line }{\b\cf1\lang1053 \par }\pard\plain \nowidctlpar\adjustright \lang2057 {\b\lang1053 7.1 Transposition Table storing winning card ranks \par }\pard \nowidctlpar\tx360\adjustright {\b\lang1053 \par }{\lang1053 For the outcome of played tricks, only card ranks that are winning due to their ranks matter: \par Assume that the last two tricks of a deal without trumps looks like the following: \par Trick 12: Leading hand North plays heart A, East, South and West follow by hearts Q, 9 and 7 respectively. \par Trick 13: North then leads spade A, the other hands plays diamonds J, 8,3 in that order. \par \par In trick 12, heart A wins by rank. In trick 13, spade A wins but not by rank. \par The sequence of cards could have been the following without changing the outcome: \par Trick 12: heart A, heart x, heart x, heart x \par Trick 13: spade x, diamond x, diamond x, diamond x \par where x is any rank below lowest winning rank. \par \par The cards that win by rank are recorded during the search and backed up similarly to the search value. If a card wins by rank and there are equivalent cards, e.g. only spade A is searched from a sequence o f AKQ, then also the other cards K and Q must be recorded as having won by rank. \par \par The cards winning by rank are stored in the Transposition Table as relative ranks, however any rank larger than the lowest winning rank in the suit are also stored as \'94winning ranks\'94 . Using relative ranks rather than absolute ranks considerably increases the number of positions that match this Transposition Table entry:\line As an example, assume that there are only 4 cards left in a suit, A, Q, 9, 7 where each hand has one card in the suit. Then any combination of ranks, e.g. 8, 6, 3, 2 that preserves the relative order of ranks between hands will cause a match. \par \par In the state position information absolute ranks are used, it is only in the Transposition Table where the ranks are stored as relatives. \par \par }\pard \fi-420\li420\nowidctlpar\tx420\adjustright {\b \par }\pard \nowidctlpar\adjustright {\b 7.2 Backing up the winning ranks \par }\pard \nowidctlpar\tx420\adjustright {\b \par }{At the search termination, either at the last trick or at a cutoff, the cards that have won by rank are backed up in the search tree together with the search value. \par As this information propagates upwards, it is aggregated with backed up information from other tree branches. \par At a search cutoff, }{\i\lang1053 MergeMoveData }{\lang1053 merges the information (V is a union): \par }{ \par }\pard \fi-420\li420\nowidctlpar\tx420\adjustright {(winning ranks of all suits for current depth) = (winning ranks of all suits for depth - 1) V (possible winning rank for the current move causing the cutoff) \par \par For each new move not causing cutoff, }{\i\lang1053 MergeAllMovesData }{\lang1053 merges: \par \par }{(winning ranks of all suits for current depth) = (winning ranks of all suits for current depth) V (winning ranks of all suits for depth - 1) V (possible winning rank for the current move) \par }\pard \nowidctlpar\tx420\adjustright { \par }\pard \fi-420\li420\nowidctlpar\tx420\adjustright {\b \par 7.3\tab }{\b\lang1053 Checking the current position for a Transposition Table entry match \par \par }\pard \nowidctlpar\tx420\adjustright {\cf1\lang1053 The "Transposition Table" has a tree structure rather than a table, consisting of 2 interconnected trees. \par For deciding if there is a match, input is the position state data, including the cards left to play and the current leading hand. \par There are \'94root pointers\'94 per number of tricks left and per leading hand which each points to the root of a tree of \'94suit lengths combination\'94 nodes. Each such node includes a 64-bit code that uniquely defines one combination of suit lengths for the hands. Th e nodes are ordered such that the value of the 64-bit code in a parent node is higher than the 64-bit code of its left child but lower than the 64-bit code of its right child. So to find the node with the suit lengths combination for the actual position, a binary search is made. The basic binary search algorithm is described in [Knuth]. \par Each \'94suit length combination node\'94 points to the root of a tree consisting of \'94winning cards nodes\'94, ie. cards that win by rank. (So the Transposition Table is really a number of trees, a forest.) \par When a position is checked for a possible Transposition Table match, a tree branch is selected consisting of 4 subsequent \'94winning cards nodes\'94, each \'94winning cards node\'94 includes an aggregate of all winning cards for one suit. Th is branch is followed as long as the \'94winning cards\'94 also can be found in the current position. (Note that the ranks of the \'94winning card nodes\'94 are relative, so the ranks of the current position must first be translated from absolute to relative ranks.) When the \'94winning cards node\'94 no longer matches with the current position and there is no other alternative \'94winning cards node\'94 that fits, then the search backs up and tries an alternative \'94winning cards node\'94 on a higher level. \par \line When the last of the 4 subsequent \'94winning cards nodes\'94 containing clubs is reached, it points to a \'94set of positions node\'94. Its stored upper and lower value bounds are checked against the number of tricks won so far by the player \rquote s side and the target value. The following conditions are then checked, assuming that it is the North/South side that is the player\rquote s side: \par \par If the sum of the stored lower value bound and the number of tricks won so far for the player\rquote s side is equal or larger than target, then target can be reached for the player\rquote s side in the current position. Search on this depth is terminated and TRUE is returned. \par \par If the sum of the stored upper value bound and the number of tricks won so far for the player\rquote s side is less than target, then reaching target can be prevented by the opponents to the player\rquote s side in the current position. Search on this depth is terminated and FALSE is returned. \par \par If instead it is East/West that is the player\rquote s side, the following conditions apply: \par \par If the sum of number of tricks remaining and the number of tricks won so far for the player\rquote s side minus the upper value bound is equal or larger than target, then target can be reached for the player\rquote s side in the current position. Search on this depth is terminated and TRUE is returned. \par \par If the sum of number of tricks remaining and the number of tricks won so far for the player\rquote s side minus the lower value bound is less than target, then reaching target can be prevented by the opponents to the player\rquote s side in the current position. Search on this depth is terminated and FALSE is returned. \par \par For all other cases, the search continues for the current depth. \par \par For example, take the previous example with 2 tricks remaining with spade rank order 1 at North. (Rank order 1 is highest rank.) The hearts have rank orders 1 at North, 2 at East, 3 at South and 4 at West. The diamond rank orders are orders 1 at East, 2 at South and 3 at West. North is leading hand. \par The \'94root pointer\'94 is now defined by the number of tricks remaining (=2) and North as leading hand. \par The \'94root pointer\'94 points to the root node of its \'94suit lengths combination\'94 tree. The 64-bit integer coded from the suit lengths for all suits and hands is now searched within the tree. When the node is found with matching 64-bit suit lengths code, this node will point to the root of its \'94winning card\'94 tree. \par This pointer points to a "winning cards node" containing spade rank order 1 at North which fits with the current position. This \'94winning cards node\'94 points to another "winning cards node" containing hearts rank orders 1 at North and 2 at East which also fits the current position. Next \'94winning cards node\'94 pointed to contains diamonds order 1 at South, which does not match the current position. However, there is an alternative \'94winning cards node\'94 that has diamonds order 1 at East, which fits. (If there had been no alternative \'94winning cards node \'94 which fitted, the search had backed up to the previous \'94winning cards node\'94 to see if there was an alternative \'94winning cards node\'94 on this level which also fitted.) The next \'94winning cards node\'94 pointed to is for clubs. This node is empty, which fits the current position which have no clubs. \par This \'94winning cards node\'94 points to a "set of positions node\'94 which have upper and lower value bounds defined. The conditions for these bounds are assumed to be fulfilled causing search termination on this depth, as described earlier. \par \par The usage of upper and lower value bounds in transposition tables is described in [Chang] and [Kupferschmid, Helmert].}{\b\lang1053 \par }\pard \nowidctlpar\adjustright {\b\lang1053 \par \par }{\pard\plain \nowidctlpar\adjustright \f1\fs20\lang1053 {\object\objemb\objw9932\objh8477\objscalex98\objscaley98{\*\objclass Word.Picture.8}{\*\objdata 01050000020000000f000000576f72642e506963747572652e3800000000000000000000b20000 d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffdffffff1b000000fefffffffeffffff05000000060000000700000008000000090000000a0000000b000000feffffff0d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a000000feffffff3c0000001d0000001e00 00001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b000000fefffffffeffffff 3e0000003f0000004000000041000000420000004300000044000000450000004600000047000000feffffff490000004a0000004b0000004c0000004d0000004e0000004f000000feffffff51000000520000005300000054000000550000005600000057000000feffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff040000000709020000000000c00000000000004600000000000000000000000090b1 f73983d8ca0103000000400100000000000001004f006c00650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 0000000000000000000000001400000000000000440061007400610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0002010100000003000000ffffffff0000000000000000000000000000000000000000000000000000 0000000000000000000004000000001000000000000031005400610062006c006500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000201ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000c0000001c1d000000000000feffffff02000000fefffffffefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000020000000000000000000000000000000038899303000000000000000000000000000000000000000000000000000000000000000000000000000000000100feff030a0000ffffffff0709020000000000c0000000000000460a00 0000576f72642d62696c64000a0000004d53576f7264446f63000f000000576f72642e506963747572652e3800f439b27100000000000000000000000000000000000000000000000000000000000000000000000000cb3b0000422a00000000000000000300000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff3c0000003c00000060150c0660150c0600000000000000006015 0c06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000716000000000000192b0180ffffffff00000000000000000000000000000000000000000000000098670000ffffffffffffffff0100000001000000 18000000ffffffff1800000000000000010000000200000000000000006f000071000071f0dd030016020000440064000000000000000200000000000000000000000000de024e023802380200000000000000000000000000000000000000000000000000000000000000000f0004f03c000000b2040af0080000003004 0000000a000043000bf018000000044107000000810111000010bf0100001000ff0100000800000010f004000000000000c0320007f0860100000304bd0271d6ceffbe413ae425c4c635b470ff0062010000040000004400000000002f0160211bf05a010000bd0271d6ceffbe413ae425c4c635b470ec010000feff0000 ffff0000970001007a000100181d0700e8b705002801000000fe789c6d91bd4a034110c7ff3bb7d124063d35a451c26191548af8043e805aa8905af422575c0e72c1235adb585909f63e84858d2f213e8485205aa8b8cecc2646c181b99dcfdfccee195480e00d4009cb10a9b3b6a6e6d08463b1ea77b2fed12cb693c37e 9667dd41247e89e333e4dc9713ab4667b856c207859856d21dc9d710adec0df3419c025be5ee3950450b17467232e1f1691196ed55233b006424e5490f4e41b8d46abb8985fd248df368272ea2dd2c3de8e1f6e6a5b8678dd65f0ba17b92515245e74f98b2d527e954a16925a1cce73b47033f8a7c3cd0ea253bc495eef9 5fafd5f3f917632c63b6cf07ca6e2ab1618f718290bdc95e62d5697e145bd358c8ba519558a014f0eb9ea293f4d0460d8d51257ebaffde543ada46fe9e7f577fb76f07f548500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000f000a0001005b000f0002000000000000002400 0040f1ff02002400000006004e006f0072006d0061006c0000000200000004006d481d0400000000000000000000000000000000000042004140f2ffa1004200000019005300740061006e00640061007200640073007400790063006b0065007400650063006b0065006e0073006e006900740074000000000000000000 0000000000000000180100001d01000022010000270100002c01000031010000870100008c010000910100009f010000ad01000081020000860200008b02000090020000950200009b020000a1020000a7020000ad020000b3020000b9020000bf020000c0020000f90200002103000001000000000000000000ffffffff a80400000000000001000000000000000000ffffffffbb0400000000000001000000000000000000ffffffffb90400000000000001000000000000000000ffffffffb80400000000000001000000000000000000ffffffffb50400000000000001000000000000000000ffffffffb7040000000000000100000000000000 0000ffffffffc10400000000000001000000000000000000ffffffffb30400000000000001000000000000000000ffffffffbd0400000000000001000000000000000000ffffffffac0400000000000001000000000000000000ffffffffad0400000000000001000000000000000000ffffffff51040000000000000100 0000000000000000ffffffffba0400000000000001000000000000000000ffffffffbc0400000000000001000000000000000000ffffffffbf0400000000000001000000000000000000ffffffffc00400000000000001000000000000000000ffffffffdb0400000000000001000000000000000000ffffffffde040000 0000000001000000000000000000ffffffffdf0400000000000001000000000000000000ffffffffe00400000000000001000000000000000000ffffffffe10400000000000001000000000000000000ffffffffe20400000000000001000000000000000000ffffffffe304000000000000ffffffff000000000100ffff ffff000000000000000001000000000000000000ffffffffe8040000000000001700000001000000000000000000000000000000000000000000180100001d01000022010000270100002c01000031010000870100008c010000910100009f010000ad01000081020000860200008b02000090020000950200009b020000 a1020000a7020000ad020000b3020000b9020000bf020000c0020000f9020000fc0200000000000000000100000000000200000000000300000000000400000000000500000000000600000000100700000000000800000000000900000000000a00000000000b00000000000c00000000000d00000000000e0000000000 0f0000000000100000000000110000000000120000000000130000000000140000000000150000000000160000000000170000000008180000000000ffff0000000000000000210300000700001400000000ffffffff010000000420ffff0100000000000000000021030000000000000000000400002107000006000000 00040000ac0600002107000007000000090000000004000020070000080000000f0000f06c000000000006f0180000000208000002000000d80000000100000001000000eb0000001f0001f02c000000320007f0240000000304d8998231e936ac9340b5972a230f4de0ff00c20c000000000000ffffffff000000004000 1ef110000000ffff00000000ff0080808000f7000010000f0002f0a00c0000100008f00800000026000000ea0400000f0003f03e0c00000f0004f028000000010009f0100000000000000000000000000000000000000002000af00800000000040000050000000f0004f04e00000012000af00800000051040000000a00 0033000bf012000000800000000c00bf0110001000ff0108000800000010f00400000000000000000011f0040000001100000000000df00400000000000c000f0004f04e00000012000af008000000a8040000000a000033000bf012000000800000000100bf0110001000ff0108000800000010f0040000000200000000 0011f0040000002700000000000df004000000000001000f0004f04200000012000af008000000ac040000000a000013000bf006000000800000000a00000010f00400000007000000000011f0040000000d00000000000df00400000000000a000f0004f04200000012000af008000000ad040000000a000013000bf006 000000800000000b00000010f00400000003000000000011f0040000000a00000000000df00400000000000b000f0004f05400000042010af008000000b0040000000a000063000bf0240000004401040000007f0100000100bf0100001000ce0102000000d70100000000ff0118001800000010f0040000002400000000 0011f004000000050000000f0004f04800000012000af008000000b3040000000a000023000bf00c0000008000000008008a00b3040000000010f0040000000b000000000011f0040000000f00000000000df004000000000008000f0004f04800000012000af008000000b5040000000a000023000bf00c000000800000 0005008a00b5040000000010f0040000000a000000000011f0040000001000000000000df004000000000005000f0004f04800000012000af008000000b7040000000a000023000bf00c0000008000000006008a00b7040000000010f00400000019000000000011f0040000001c00000000000df004000000000006000f 0004f04800000012000af008000000b8040000000a000023000bf00c0000008000000004008a00b8040000000010f00400000018000000000011f0040000001b00000000000df004000000000004000f0004f04200000012000af008000000b9040000000a000013000bf006000000800000000300000010f0040000001b 000000000011f0040000001d00000000000df004000000000003000f0004f04200000012000af008000000ba040000000a000013000bf006000000800000000d00000010f0040000001c000000000011f0040000001e00000000000df00400000000000d000f0004f04800000012000af008000000bb040000000a000023 000bf00c0000008000000002008a00bb040000000010f00400000015000000000011f0040000001b00000000000df004000000000002000f0004f04200000012000af008000000bc040000000a000013000bf006000000800000000e00000010f0040000001d000000000011f0040000001f00000000000df00400000000 000e000f0004f04200000012000af008000000bd040000000a000013000bf006000000800000000900000010f00400000023000000000011f0040000000e00000000000df004000000000009000f0004f04200000012000af008000000bf040000000a000013000bf006000000800000000f00000010f004000000220000 00000011f0040000000e00000000000df00400000000000f000f0004f04200000012000af008000000c0040000000a000013000bf006000000800000001000000010f00400000021000000000011f0040000000e00000000000df004000000000010000f0004f04200000012000af008000000c1040000000a000013000b f006000000800000000700000010f00400000001000000000011f0040000001100000000000df004000000000007000f0004f04e00000042010af008000000c3040000000a000053000bf01e0000004401040000007f0100000100bf0100001000d10101000000ff0110001000000010f00400000005000000000011f004 000000180000000f0004f04e00000042010af008000000c5040000000a000053000bf01e0000004401040000007f0100000100bf0100001000d10101000000ff0110001000000010f00400000009000000000011f004000000120000000f0004f04e00000042010af008000000c6040000000a000053000bf01e00000044 01040000007f0100000100bf0100001000d10101000000ff0110001000000010f0040000000f000000000011f004000000160000000f0004f04e00000042010af008000000c7040000000a000053000bf01e0000004401040000007f0100000100bf0100001000d10101000000ff0110001000000010f004000000120000 00000011f004000000190000000f0004f04e00000042010af008000000c8040000000a000053000bf01e0000004401040000007f0100000100bf0100001000d10101000000ff0110001000000010f00400000013000000000011f0040000001c0000000f0004f04e00000042010af008000000c9040000000a000053000b f01e0000004401040000007f0100000100bf0100001000d10101000000ff0110001000000010f0040000001a000000000011f0040000001e0000000f0004f04e00000042010af008000000ca040000000a000053000bf01e0000004401040000007f0100000100bf0100001000d10101000000ff0110001000000010f004 00000017000000000011f0040000001e0000000f0004f04e00000042010af008000000cb040000000a000053000bf01e0000004401040000007f0100000100bf0100001000d10101000000ff0110001000000010f00400000016000000000011f0040000001e0000000f0004f04e00000042010af008000000cc04000000 0a000053000bf01e0000004401040000007f0100000100bf0100001000d10101000000ff0110001000000010f0040000001f000000000011f004000000230000000f0004f054000000a20c0af008000000db040000000a000043000bf0180000008000000011008a00db040000bf0100001000ff0100000800000010f004 00000008000000000011f0040000002d00000000000df004000000000011000f0004f054000000a20c0af008000000de040000000a000043000bf0180000008000000012008a00de040000bf0100001000ff0100000800000010f00400000011000000000011f0040000002300000000000df004000000000012000f0004 f054000000a20c0af008000000df040000000a000043000bf0180000008000000013008a00df040000bf0100001000ff0100000800000010f00400000014000000000011f0040000002300000000000df004000000000013000f0004f054000000a20c0af008000000e0040000000a000043000bf0180000008000000014 008a00e0040000bf0100001000ff0100000800000010f00400000010000000000011f0040000002300000000000df004000000000014000f0004f054000000a20c0af008000000e1040000000a000043000bf0180000008000000015008a00e1040000bf0100001000ff0100000800000010f0040000000e000000000011 f0040000002400000000000df004000000000015000f0004f054000000a20c0af008000000e2040000000a000043000bf0180000008000000016008a00e2040000bf0100001000ff0100000800000010f0040000000d000000000011f0040000002300000000000df004000000000016000f0004f054000000a20c0af008 000000e3040000000a000043000bf0180000008000000017008a00e3040000bf0100001000ff0100000800000010f0040000000c000000000011f0040000002300000000000df004000000000017000f0004f04e00000042010af008000000e6040000000a000053000bf01e0000004401040000007f0100000100bf0100 001000d10101000000ff0110001000000010f00400000020000000000011f004000000220000000f0004f04e00000042010af008000000e7040000000a000053000bf01e0000004401040000007f0100000100bf0100001000d10101000000ff0110001000000010f0040000001e000000000011f004000000210000000f 0004f04800000012000af008000000e8040000000a000023000bf00c0000008000000019008a00e8040000000010f00400000004000000000011f0040000000f00000000000df004000000000019000f0004f04e00000042010af008000000ea040000400a000053000bf01e0000004401040000007f0100000100bf0100 001000d10101000000ff0110001000000010f00400000006000000000011f0040000000d0000000f0004f04200000012000af00800000001040000000e000053000bf01e000000bf0100001000cb0100000000ff01000008000403090000003f0301000100000011f0040000000100000000000000010000000200000003 0000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f0000002000000021000000220000 0023000000240000002103000051040000501700003e000000d02400008e070000740000000000c1040000e0170000fe18000060250000ee1c0000740000000000a8040000501700007e0b0000f0250000ce120000740000000000ad040000600a0000ce000000e00e00009e030000740000000000e804000080020000de 050000e00e0000ae080000740001000000c3040000c00400009e03000070060000de050000740000000000ea04000010030000ae080000e00500007e0b0000740000000000ac04000060010000ce000000500500009e030000740000000000db040000500500007e0b000020080000be0d0000740001000000c5040000c0 0400009e0c0000400900009e0c0000740000000000b5040000400900007e0b0000100c0000be0d0000740001000000b3040000f00100007e0b0000c0040000be0d0000740001000000e3040000b0110000ee130000801400002e160000740001000000e2040000600a0000ee130000300d00002e160000740001000000e1 04000010030000ee130000e00500002e160000740001000000c604000010030000be0d0000100300001e110000740000000000e0040000100300004e0e0000e00500008e100000740001000000de040000500500001e110000200800005e130000740001000000c7040000c00400003e120000400900003e120000740000 000000c8040000100c00003e120000901000003e120000740000000000df040000a00c00001e110000700f00005e130000740001000000bb040000901000001e110000601300005e130000740001000000cb040000b01100005e130000b0110000be160000740000000000ca040000600a00005e130000600a0000be1600 00740000000000b8040000400900001e110000100c00005e130000740001000000b7040000f00100001e110000c00400005e130000740001000000c9040000100300005e13000010030000be160000740000000000b9040000f0010000be160000c0040000fe180000740000000000ba04000040090000be160000100c00 00fe180000740000000000bc04000090100000be16000060130000fe180000740000000000e7040000b0110000fe180000b0110000ae1a0000740000000000cc04000010030000fe18000010030000ae1a0000740000000000e6040000600a0000fe180000600a0000ae1a0000740000000000c004000090100000ae1a00 0060130000ee1c0000740000000000bf04000040090000ae1a0000100c0000ee1c0000740000000000bd040000f0010000ae1a0000c0040000ee1c0000740000000000b004000070060000ee01000040090000ee01000074000000000000000000260000002d0000002e0000003300000034000000390000003a0000003e 0000003f000000490000004e00000055000000560000005b000000600000006300000064000000680000006d00000073000000860000008d0000008e000000930000009400000098000000a1000000a5000000a6000000ae000000af000000b6000000b7000000bc000000bd000000c1000000ca000000ce000000cf0000 00d3000000d7000000db000000dc000000e0000000e1000000e700000002010000060100000701000009010000140100001b0100001c01000021010000230100002701000035010000390100003e010000410100004301000046010000480100004b0100004d010000500100005201000055010000690100006c0100006e 01000073010000740100007e0100008d01000092010000970100009c0100009d010000a2010000a3010000a8010000ad010000b0010000b2010000b5010000b7010000bb010000c5010000c9010000e1010000e3010000ee010000f2010000fb01000002020000090200000f020000170200001b0200001f020000220200 0023020000270200002802000032020000360200003a0200003b020000420200004f02000054020000560200005a0200005b0200005f02000060020000670200007402000078020000790200007f020000870200008b0200008f02000092020000930200009a0200009b0200009f020000a0020000a4020000a7020000aa 020000ac020000af020000b1020000b4020000b6020000b9020000cd020000d1020000d3020000d7020000d9020000dd020000df020000e3020000e6020000ea020000ee020000f3020000f4020000f8020000010300000403000005030000090300000a030000110300002203000007001c0007001c0007001c0007001c 0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007 001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c 0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c0007001c000700ff400080010000000000000000006021b0010000000000000000000000000000000000000000021000000000000000210300007000000800400000030000004716900100000202 0603050405020304ef3a00e0417800c00900000000000000ff00000000000000540069006d006500730020004e0065007700200052006f006d0061006e00000035169001020005050102010706020507000000000000001000000000000000000000008000000000530079006d0062006f006c000000332690010000020b 0604020202020204ff3a00e0437800c00900000000000000ff0000000000000041007200690061006c0000002200040070088818000018050000a901000000009275c3a69275c3a6000000000200000000000000000000000000010001000000040003100100000000000000000000000100010000000100000000000000 210300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a506c007b400b40080001e30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000002000000c401ffff120000000000000000000000000000000a0042006f0020004800610067006c0075006e0064000a0042006f0020004800610067006c0075006e006400000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010043006f006d0070004f0062006a00000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000120002010200000006000000ffffffff000000000000000000000000000000000000000000000000000000000000000000000000010000005b0000000000000003004f0062006a0049006e0066006f0000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000012000201ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000300000004000000000000004f0062006a0065006300740050006f006f006c0000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000160001010500000008000000ffffffff000000000000000000000000000000000000000090b1f73983d8ca0190b1f73983d8ca0100000000000000000000000002004f006c0065005000720065007300300030003000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000018000201ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000001c000000ee3e000000000000ffffffff030000000400000001000000ffffffff 00000000000000006d440000673a0000c63e0000010009000003631f000008003100000000001400000026060f001e00ffffffff040014000000576f72640e004d6963726f736f667420576f7264050000000b0200000000050000000c02cc0d2a101c000000fb021000070000000000bc02000000000102022253797374 656d0000640e666f00000a0022008a0100000000ffffffff48d41200040000002d010000050000000201010000001c000000fb02adff0000000000009001000000000440001254696d6573204e657720526f6d616e0030cb120010da1c76c0601f76640e666f040000002d01010005000000090200000000050000000201 0100000007000000fc020000ffffff000000040000002d01020008000000fa0200000600000000000002040000002d010300070000001b042703580f1a00b70907000000fc020000ffffff000000040000002d01040004000000f001020008000000fa0200000000000000000000040000002d01020004000000f0010300 030000001e000700000016040503190f3b00f609050000000201010000000500000014023c00f609050000002e010100000020000000320a3c00f6090e000400000000002a10cc0d4120706f696e74657220706572203b0015002a002a0017002900170025001c0015002a0025001c001500050000002e01000000000500 00001402000000000500000014023c00c70b050000002e01010000001f000000320a3c00c70b0d000400000000002a10cc0d6e6f206f6620747269636b73200029002a0015002a001b00150017001c00170025002a0020001500050000002e0100000000050000001402000000000500000014023c00570d050000002e01 010000001d000000320a3c00570d0c000400000000002a10cc0d6c65667420616e6420706572170025001c0017001500250029002a0015002a0025001c00050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014029c00f609050000002e010100000020000000 320a9c00f6090e000400000000002a10cc0d6c656164696e672068616e642e201700250025002a0017002900290016002900250029002a0015001500050000002e0100000000050000001402000000000500000014029c00cb0b050000002e010100000020000000320a9c00cb0b0e000400000000002a10cc0d506f696e 747320746f20746865202f002a001700290017002000150017002a0015001800290025001500050000002e0100000000050000001402000000000500000014029c00810d050000002e010100000017000000320a9c00810d08000400000000002a10cc0d726f6f74206f66201c002a002a00170015002a001b0015000500 00002e0100000000050000001402000000000500000014029c00770e050000002e010100000010000000320a9c00770e03000400000000002a10cc0d69747300170017002000050000002e0100000000050000001402000000000500000002010100000005000000020101000000050000001402fc00f609050000002e01 0100000013000000320afc00f60905000400000000002a10cc0d74726565200017001c00250025001500050000002e010000000005000000140200000000050000001402fc00880a050000002e010100000020000000320afc00880a0e000400000000002a10cc0d636f6e73697374696e67206f662025002a0029002000 17002000170018002a00290015002a001b001500050000002e010000000005000000140200000000050000001402fc00480c050000002e010100000013000000320afc00480c05000400000000002a10cc0d73756974200021002900170017001500050000002e010000000005000000140200000000050000001402fc00 d50c050000002e010100000016000000320afc00d50c07000400000000002a10cc0d6c656e6774687320170026002a00290017002a002000050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014025c01f609050000002e01010000001d000000320a5c01f609 0c000400000000002a10cc0d636f6d62696e6174696f6e2025002a003f002a00180029002500170017002b0029001500050000002e0100000000050000001402000000000500000014025c01ab0b050000002e010100000014000000320a5c01ab0b06000400000000002a10cc0d6e6f6465732e29002a002a0025002000 1500050000002e0100000000050000001402000000000500000002010100000005000000020101000000050000001402bb01f609050000002e010100000013000000320abb01f60905000400000000002a10cc0d45616368200033002500250029001500050000002e010000000005000000140200000000050000001402 bb01b10a050000002e010100000013000000320abb01b10a05000400000000002a10cc0d73756974200020002a00170017001500050000002e010000000005000000140200000000050000001402bb013e0b050000002e010100000029000000320abb013e0b14000400000000002a10cc0d6c656e6774687320636f6d62 696e6174696f6e20170025002a002900180029002000150025002b003f002b00170029002500170017002b0029001500050000002e010000000005000000140200000000050000001402bb01f90d050000002e010100000011000000320abb01f90d04000400000000002a10cc0d6e6f646529002a002a00250005000000 2e01000000000500000014020000000005000000020101000000050000000201010000000500000014021b02f609050000002e010100000020000000320a1b02f6090e000400000000002a10cc0d706f696e747320746f20746865202a002a001700290017002000150017002a0015001700290025001500050000002e01 00000000050000001402000000000500000014021b02a60b050000002e010100000017000000320a1b02a60b08000400000000002a10cc0d726f6f74206f66201c002a002a00170015002a001b001500050000002e0100000000050000001402000000000500000014021b029c0c050000002e010100000011000000320a 1b029c0c04000400000000002a10cc0d697473201700170020001600050000002e0100000000050000001402000000000500000014021b02000d050000002e010100000017000000320a1b02000d08000400000000002a10cc0d77696e6e696e67203b00180029002a001700290029001500050000002e01000000000500 00001402000000000500000014021b02240e050000002e010100000011000000320a1b02240e04000400000000002a10cc0d63617264260025001c002a00050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014027d02f609050000002e010100000013000000 320a7d02f60905000400000000002a10cc0d747265652e0017001c00250025001500050000002e01000000000500000014020000000005000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01030008000000fa0200000600000000000002040000002d010500070000001b04d707 d00fca04b709040000002d01040004000000f0010300040000002d01020004000000f0010500030000001e00070000001604b507910feb04f60905000000020101000000040000002d01010005000000090200000000050000001402ec04f609050000002e010100000017000000320aec04f60908000400000000002a10 cc0d57696e6e696e67204f0017002900290018002a0029001500050000002e01000000000500000014020902640e050000001402ec042e0b050000002e010100000014000000320aec042e0b06000400000000002a10cc0d636172647320250025001c002a0020001500050000002e010000000005000000140200000000 050000001402ec04f30b050000002e010100000014000000320aec04f30b06000400000000002a10cc0d6e6f6465732029002a002a00250020001500050000002e010000000005000000140200000000050000001402ec04ca0c050000002e010100000013000000320aec04ca0c05000400000000002a10cc0d65616368 200025002500250029001500050000002e010000000005000000140200000000050000001402ec04770d050000002e010100000020000000320aec04770d0e000400000000002a10cc0d636f6e7461696e696e6720616c6c25002a002900170026001700290018002a0029001500250017001700050000002e0100000000 0500000014020000000005000000020101000000050000000201010000000500000014024c05f609050000002e010100000017000000320a4c05f60908000400000000002a10cc0d77696e6e696e67203b0018002a0029001800290029001500050000002e0100000000050000001402000000000500000014024c051b0b 050000002e01010000001a000000320a4c051b0b0a000400000000002a10cc0d636172647320666f7220250025001c002a00200015001b002a001c001500050000002e0100000000050000001402000000000500000014024c05560c050000002e010100000011000000320a4c05560c04000400000000002a10cc0d6f6e 65202a00290025001500050000002e0100000000050000001402000000000500000014024c05e30c050000002e010100000019000000320a4c05e30c09000400000000002a10cc0d737569742e20497420202100290017001700150015001c0017001500050000002e010000000005000000140200000000050000001402 4c05cd0d050000002e01010000001d000000320a4c05cd0d0c000400000000002a10cc0d706f696e747320746f20616e2a002a001700290017002000150017002a00150026002900050000002e0100000000050000001402000000000500000002010100000005000000020101000000050000001402ac05f60905000000 2e01010000001d000000320aac05f6090c000400000000002a10cc0d616c7465726e61746976652025001700170025001c002900250017001800290025001600050000002e010000000005000000140200000000050000001402ac056b0b050000002e010100000017000000320aac056b0b08000400000000002a10cc0d 77696e6e696e67203b0018002900290018002a0029001500050000002e010000000005000000140200000000050000001402ac05900c050000002e010100000014000000320aac05900c06000400000000002a10cc0d636172647320250025001c002a0020001500050000002e0100000000050000001402000000000500 00001402ac05550d050000002e01010000001f000000320aac05550d0d000400000000002a10cc0d6e6f64652c20746f20746865200029002a002a0025001500150017002a0015001700290025001500050000002e010000000005000000140200000000050000001402ac05f10e050000002e010100000011000000320a ac05f10e04000400000000002a10cc0d6e657874290025002a001700050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014020c06f609050000002e010100000019000000320a0c06f60909000400000000002a10cc0d726571756972656420201c0025002a00 290017001c0025002a001600050000002e0100000000050000001402000000000500000014020c06220b050000002e010100000017000000320a0c06220b08000400000000002a10cc0d77696e6e696e67203a0017002a00290018002a0029001500050000002e0100000000050000001402000000000500000014020c06 460c050000002e010100000014000000320a0c06460c06000400000000002a10cc0d636172647320250025001c002a0020001500050000002e0100000000050000001402000000000500000014020c060b0d050000002e01010000001f000000320a0c060b0d0d000400000000002a10cc0d6e6f646520666f7220746865 200029002a002a00250015001b002a001c0015001700290025001500050000002e0100000000050000001402000000000500000014020c06b20e050000002e010100000011000000320a0c06b20e04000400000000002a10cc0d6e6578742900260029001700050000002e01000000000500000014020000000005000000 020101000000050000000201010000000500000014026b06f609050000002e010100000017000000320a6b06f60908000400000000002a10cc0d7375697420696e2020002900170017001500180029001500050000002e0100000000050000001402000000000500000014026b06d80a050000002e010100000013000000 320a6b06d80a05000400000000002a10cc0d74686973200018002900170020001500050000002e0100000000050000001402000000000500000014026b06650b050000002e010100000013000000320a6b06650b05000400000000002a10cc0d74726565200017001c00250025001500050000002e010000000005000000 1402000000000500000014026b06f70b050000002e01010000002c000000320a6b06f70b16000400000000002a10cc0d6272616e636820616e6420746f206120736574206f662a001c0025002900260029001500250029002a00150017002a0015002500150020002500170015002a001b00050000002e01000000000500 00001402000000000500000002010100000005000000020101000000050000001402cb06f609050000002e01010000001a000000320acb06f6090a000400000000002a10cc0d706f736974696f6e73202a002a0020001700170017002a00290020001600050000002e010000000005000000140200000000050000001402 cb06380b050000002e010100000013000000320acb06380b05000400000000002a10cc0d6e6f6465200029002a002a0025001500050000002e010000000005000000140200000000050000001402cb06ef0b050000002e01010000001f000000320acb06ef0b0d000400000000002a10cc0d696620697420697320746865 200017001b0015001700170015001700200015001800290025001600050000002e010000000005000000140200000000050000001402cb06410d050000002e010100000017000000320acb06410d08000400000000002a10cc0d77696e6e696e67203b0018002900290018002a0029001500050000002e01000000000500 0000140200000000050000001402cb06660e050000002e010100000013000000320acb06660e05000400000000002a10cc0d636172647300250025001c002a002000050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014022d07f609050000002e0101000000 26000000320a2d07f60912000400000000002a10cc0d6e6f646520666f7220746865206c6173742029002a002a00250015001b002a001c001500170029002500150017002500200017001500050000002e0100000000050000001402000000000500000014022d07250c050000002e010100000014000000320a2d07250c 06000400000000002a10cc0d737569742e2e210029001700170015001500050000002e01000000000500000014020000000005000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01030008000000fa0200000600000000000002040000002d010500070000001b04830138025600 9300040000002d01040004000000f0010300040000002d01020004000000f0010500030000001e000700000016046101f9017700d20005000000020101000000040000002d010100050000000902000000000500000014027800d200050000002e010100000011000000320a7800d20004000400000000002a10cc0d526f 6f7437002a002a001700050000002e01000000000500000014020902640e0500000002010100000005000000020101000000050000001402da00d200050000002e010100000016000000320ada00d20007000400000000002a10cc0d706f696e746572002a002a0017002900170025001c00050000002e01000000000500 000014020000000005000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01030008000000fa0200000600000000000002040000002d010500070000001b048301340656005304040000002d01040004000000f0010300040000002d01020004000000f0010500030000001e000700 000016046101f5057700920405000000020101000000040000002d0101000500000009020000000005000000140278009204050000002e010100000011000000320a7800920404000400000000002a10cc0d526f6f7437002a002a001700050000002e01000000000500000014020902640e050000000201010000000500 0000020101000000050000001402da009204050000002e010100000016000000320ada00920407000400000000002a10cc0d706f696e746572002a002a0017002900170025001c00050000002e01000000000500000014020000000005000000020101000000040000002701ffff1000000026060f001600ffffffff0000 ab020000ca000000e0030000d300000008000000fa0205000100000000000000040000002d01030007000000fc020000000000000000040000002d010500050000000601020000002800000024031200b002cb00af02cb00ae02cc00ad02cd00ac02ce00ac02ce00ad02cf00ae02d000af02d100af02d100af02d100b002 d000b102cf00b202ce00b202ce00b102cd00b002cc00b002cb002800000024031200bb02cb00ba02cb00b902cc00b802cd00b802ce00b802cf00b802d000b902d100ba02d100bb02d100bb02d100bc02d000bd02cf00be02ce00be02ce00bd02cd00bc02cc00bc02cb002800000024031200c702cb00c602cb00c502cc00 c402cd00c402ce00c402cf00c402d000c502d100c602d100c702d100c702d100c802d000c902cf00ca02ce00ca02ce00c902cd00c802cc00c802cb002800000024031200d302cb00d202cb00d102cc00d002cd00d002ce00d002cf00d002d000d102d100d202d100d302d100d302d100d402d000d502cf00d602ce00d602 ce00d502cd00d402cc00d402cb002800000024031200df02cb00de02cb00dd02cc00dc02cd00dc02ce00dc02cf00dc02d000dd02d100de02d100df02d100df02d100e002d000e102cf00e202ce00e202ce00e102cd00e002cc00e002cb002800000024031200eb02cb00ea02cb00e902cc00e802cd00e802ce00e802cf00 e802d000e902d100ea02d100eb02d100eb02d100ec02d000ed02cf00ee02ce00ee02ce00ed02cd00ec02cc00ec02cb002800000024031200f702cb00f602cb00f502cc00f402cd00f402ce00f402cf00f402d000f502d100f602d100f702d100f702d100f802d000f902cf00fa02ce00fa02ce00f902cd00f802cc00f802 cb0028000000240312000303cb000203cb000103cc000003cd000003ce000003cf000003d0000103d1000203d1000303d1000303d1000403d0000503cf000603ce000603ce000503cd000403cc000403cb0028000000240312000f03cb000e03cb000d03cc000c03cd000c03ce000c03cf000c03d0000d03d1000e03d100 0f03d1000f03d1001003d0001103cf001203ce001203ce001103cd001003cc001003cb0028000000240312001b03cb001a03cb001903cc001803cd001803ce001803cf001803d0001903d1001a03d1001b03d1001b03d1001c03d0001d03cf001e03ce001e03ce001d03cd001c03cc001c03cb0028000000240312002703 cb002603cb002503cc002403cd002403ce002403cf002403d0002503d1002603d1002703d1002703d1002803d0002903cf002a03ce002a03ce002903cd002803cc002803cb0028000000240312003303cb003203cb003103cc003003cd003003ce003003cf003003d0003103d1003203d1003303d1003303d1003403d000 3503cf003603ce003603ce003503cd003403cc003403cb0028000000240312003f03cb003e03cb003d03cc003c03cd003c03ce003c03cf003c03d0003d03d1003e03d1003f03d1003f03d1004003d0004103cf004203ce004203ce004103cd004003cc004003cb0028000000240312004b03cb004a03cb004903cc004803 cd004803ce004803cf004803d0004903d1004a03d1004b03d1004b03d1004c03d0004d03cf004e03ce004e03ce004d03cd004c03cc004c03cb0028000000240312005703cb005603cb005503cc005403cd005403ce005403cf005403d0005503d1005603d1005703d1005703d1005803d0005903cf005a03ce005a03ce00 5903cd005803cc005803cb0028000000240312006303cb006203cb006103cc006003cd006003ce006003cf006003d0006103d1006203d1006303d1006303d1006403d0006503cf006603ce006603ce006503cd006403cc006403cb0028000000240312006f03cb006e03cb006d03cc006c03cd006c03ce006c03cf006c03 d0006d03d1006e03d1006f03d1006f03d1007003d0007103cf007203ce007203ce007103cd007003cc007003cb0028000000240312007b03cb007a03cb007903cc007803cd007803ce007803cf007803d0007903d1007a03d1007b03d1007b03d1007c03d0007d03cf007e03ce007e03ce007d03cd007c03cc007c03cb00 28000000240312008703cb008603cb008503cc008403cd008403ce008403cf008403d0008503d1008603d1008703d1008703d1008803d0008903cf008a03ce008a03ce008903cd008803cc008803cb0028000000240312009303cb009203cb009103cc009003cd009003ce009003cf009003d0009103d1009203d1009303 d1009303d1009403d0009503cf009603ce009603ce009503cd009403cc009403cb0028000000240312009f03cb009e03cb009d03cc009c03cd009c03ce009c03cf009c03d0009d03d1009e03d1009f03d1009f03d100a003d000a103cf00a203ce00a203ce00a103cd00a003cc00a003cb002800000024031200ab03cb00 aa03cb00a903cc00a803cd00a803ce00a803cf00a803d000a903d100aa03d100ab03d100ab03d100ac03d000ad03cf00ae03ce00ae03ce00ad03cd00ac03cc00ac03cb002800000024031200b703cb00b603cb00b503cc00b403cd00b403ce00b403cf00b403d000b503d100b603d100b703d100b703d100b803d000b903 cf00ba03ce00ba03ce00b903cd00b803cc00b803cb002800000024031200c303cb00c203cb00c103cc00c003cd00c003ce00c003cf00c003d000c103d100c203d100c303d100c303d100c403d000c503cf00c603ce00c603ce00c503cd00c403cc00c403cb002800000024031200cf03cb00ce03cb00cd03cc00cc03cd00 cc03ce00cc03cf00cc03d000cd03d100ce03d100cf03d100cf03d100d003d000d103cf00d203ce00d203ce00d103cd00d003cc00d003cb0005000000060101000000040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff010007000000fc020000ffffff000000040000002d01 050008000000fa0200000600000000000002040000002d010600070000001b04bb05fc01ca04cf00040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e000700000016049905bd01eb040e0105000000020101000000040000002d01010005000000090200000000050000001402 ee040e01050000002e010100000010000000320aee040e0103000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa020000060000000000000204000000 2d010600070000001b04bb050805ca04db03040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e000700000016049905c904eb041a0405000000020101000000040000002d01010005000000090200000000050000001402ee041a04050000002e010100000010000000320aee04 1a0403000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b041308fc012207cf0004000000 2d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604f107bd0143070e0105000000020101000000040000002d0101000500000009020000000005000000140246070e01050000002e010100000010000000320a46070e0103000400000000002a10cc0d57696e034f001700 2900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b04130808052207db03040000002d01040004000000f0010500040000002d0102000400 0000f0010600030000001e00070000001604f107c90443071a0405000000020101000000040000002d0101000500000009020000000005000000140246071a04050000002e010100000010000000320a46071a0403000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e 05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b046b0afc017a09cf00040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604490abd01 9b090e0105000000020101000000040000002d010100050000000902000000000500000014029e090e01050000002e010100000010000000320a9e090e0103000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000 fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b046b0a08057a09db03040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604490ac9049b091a0405000000020101000000040000002d010100 050000000902000000000500000014029e091a04050000002e010100000010000000320a9e091a0403000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000 fa0200000600000000000002040000002d010600070000001b04130814082207e706040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604f107d5074307260705000000020101000000040000002d01010005000000090200000000050000001402460726070500 00002e010100000010000000320a4607260703000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d0106000700 00001b046b0a14087a09e706040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604490ad5079b09260705000000020101000000040000002d010100050000000902000000000500000014029e092607050000002e010100000010000000320a9e09260703000400 000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b040f0cfc011e0bcf00040000002d0104000400 0000f0010500040000002d01020004000000f0010600030000001e00070000001604ed0bbd013f0b0e0105000000020101000000040000002d01010005000000090200000000050000001402420b0e01050000002e010100000010000000320a420b0e0103000400000000002a10cc0d534f50032e003c002f0005000000 2e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b040f0c08051e0bdb03040000002d01040004000000f0010500040000002d01020004000000f0010600 030000001e00070000001604ed0bc9043f0b1a0405000000020101000000040000002d01010005000000090200000000050000001402420b1a04050000002e010100000010000000320a420b1a0403000400000000002a10cc0d534f50032e003c002f00050000002e01000000000500000014020902640e050000000201 01000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b040f0c14081e0be706040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604ed0bd5073f0b26070500 0000020101000000040000002d01010005000000090200000000050000001402420b2607050000002e010100000010000000320a420b260703000400000000002a10cc0d534f50032e003c002f00050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffff ff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b040f0c940f6a0af309040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604ed0b550f8b0a320a05000000020101000000040000002d010100050000000902 000000000500000014028c0a320a050000002e010100000026000000320a8c0a320a12000400000000002a10cc0d536574206f6620706f736974696f6e7320282e002500170015002a001b0015002a002a0020001700170017002a002a00200015001c00050000002e01000000000500000014020902640e050000001402 8c0a690c050000002e010100000013000000320a8c0a690c05000400000000002a10cc0d534f502920002e003c002f001c001500050000002e0100000000050000001402000000000500000014028c0a330d050000002e010100000013000000320a8c0a330d05000400000000002a10cc0d6e6f6465730029002a002a00 25002000050000002e0100000000050000001402000000000500000002010100000005000000020101000000050000001402ec0a320a050000002e010100000031000000320aec0a320a19000400000000002a10cc0d636f6e7461696e696e672074686520706f736974696f6e73200025002a0029001700250017002900 18002a002900150017002900250015002a002a0020001700180017002a00290020001600050000002e010000000005000000140200000000050000001402ec0a630d050000002e010100000019000000320aec0a630d09000400000000002a10cc0d757070657220616e642029002a002a0025001c001500250029002a00 050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014024c0b320a050000002e010100000014000000320a4c0b320a06000400000000002a10cc0d6c6f7765722017002b003a0025001c001500050000002e010000000005000000140200000000050000001402 4c0b040b050000002e010100000014000000320a4c0b040b06000400000000002a10cc0d76616c756520290025001800290025001500050000002e0100000000050000001402000000000500000014024c0bcd0b050000002e010100000014000000320a4c0bcd0b06000400000000002a10cc0d626f756e642e2a002a00 2a0029002a001500050000002e010000000005000000140200000000050000000201010000000500000002010100000005000000020101000000040000002701ffff1000000026060f001600ffffffff0000f70100007e010000b40200007702000008000000fa0200000600000000000000040000002d01050007000000 fc020100000000000000040000002d0106000800000025030200fb0182018a024002040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303006e025202af027202a2022b02040000002d010200040000002d01040004000000f00105000800000026060f000600 ffffffff01001000000026060f001600ffffffff0000f70100001e050000e00300006805000008000000fa0200000600000000000000040000002d010500040000002d0106000800000025030200fb0142059c034205040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a00 0000240303009a036305db0342059a032205040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff000022010000b60500006c0100002707000008000000fa0200000600000000000000040000002d010500040000002d01060008000000 250302004701ba054701e306040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303002601e106470122076701e106040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff0000 f701000076070000e0030000c007000008000000fa0200000600000000000000040000002d010500040000002d0106000800000025030200fb019a079c039a07040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303009a03bb07db039a079a037a0704000000 2d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff00000305000076070000ec060000c007000008000000fa0200000600000000000000040000002d010500040000002d010600080000002503020007059a07a8069a07040000002d0103000400 0000f001050007000000fc020000000000000000040000002d0105000a00000024030300a606bb07e7069a07a6067a07040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff0000220100000e0800006c0100007f09000008000000fa02 00000600000000000000040000002d010500040000002d01060008000000250302004701120847013b09040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303002601390947017a0967013909040000002d010200040000002d01040004000000f00105000800 000026060f000600ffffffff01001000000026060f001600ffffffff00002e0400000e080000780400007f09000008000000fa0200000600000000000000040000002d010500040000002d01060008000000250302005304120853043b09040000002d01030004000000f001050007000000fc0200000000000000000400 00002d0105000a000000240303003204390953047a0973043909040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff00003a0700000e080000840700007f09000008000000fa0200000600000000000000040000002d01050004000000 2d01060008000000250302005f0712085f073b09040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303003e0739095f077a097f073909040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f00 1600ffffffff000022010000660a00006c010000230b000008000000fa0200000600000000000000040000002d010500040000002d010600080000002503020047016a0a4701df0a040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303002601dd0a47011e0b 6701dd0a040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff0100040000002d010600040000002d010300070000001b04bb056403ca043702040000002d010400040000002d010200030000001e000700000016049c052803e804730205000000020101000000040000002d01 010005000000090200000000050000001402eb047302050000002e010100000011000000320aeb04730204000400000000002a10cc0d416c742e3b00170017001500050000002e01000000000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b04 1308640322073702040000002d010400040000002d010200030000001e00070000001604f40728034007730205000000020101000000040000002d0101000500000009020000000005000000140243077302050000002e010100000011000000320a4307730204000400000000002a10cc0d416c742e3b00170017001500 050000002e01000000000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b041308700622074305040000002d010400040000002d010200030000001e00070000001604f407340640077f0505000000020101000000040000002d01010005000000 09020000000005000000140243077f05050000002e010100000011000000320a43077f0504000400000000002a10cc0d416c742e3b00170017001500050000002e01000000000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b04e7067402f605 4701040000002d010400040000002d010200030000001e00070000001604c80638021406830105000000020101000000040000002d0101000500000009020000000005000000140217068301050000002e010100000011000000320a1706830104000400000000002a10cc0d4e6578743c00250029001700050000002e01 000000000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b043f0974024e084701040000002d010400040000002d010200030000001e00070000001604200938026c08830105000000020101000000040000002d01010005000000090200000000 0500000014026f088301050000002e010100000011000000320a6f08830104000400000000002a10cc0d4e6578743c00250029001700050000002e01000000000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b043f0980054e08530404000000 2d010400040000002d010200030000001e00070000001604200944056c088f0405000000020101000000040000002d010100050000000902000000000500000014026f088f04050000002e010100000011000000320a6f088f0404000400000000002a10cc0d4e6578743c00250029001700050000002e01000000000500 000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b043f098c084e085f07040000002d010400040000002d010200030000001e00070000001604200950086c089b0705000000020101000000040000002d01010005000000090200000000050000001402 6f089b07050000002e010100000011000000320a6f089b0704000400000000002a10cc0d4e6578743c00250029001700050000002e01000000000500000014020902640e05000000020101000000040000002701ffff1000000026060f001600ffffffff00002e040000660a000078040000230b000008000000fa020000 0600000000000000040000002d010500040000002d010600080000002503020053046a0a5304df0a040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303003204dd0a53041e0b7304dd0a040000002d010200040000002d01040004000000f001050008000000 26060f000600ffffffff01001000000026060f001600ffffffff00003a070000660a000084070000230b000008000000fa0200000600000000000000040000002d010500040000002d01060008000000250302005f076a0a5f07df0a040000002d01030004000000f001050007000000fc02000000000000000004000000 2d0105000a000000240303003e07dd0a5f071e0b7f07dd0a040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff010007000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010700070000001b049f03340672020b010400 00002d01040004000000f0010500040000002d01020004000000f0010700030000001e000700000016047d03f50593024a0105000000020101000000040000002d0101000500000009020000000005000000140294024a01050000002e010100000017000000320a94024a0108000400000000002a10cc0d54726565206f 662034001c002500240015002a001b001500050000002e01000000000500000014020902640e05000000140294025202050000002e010100000014000000320a9402520206000400000000002a10cc0d6e6f6465732029002a002a00250020001500050000002e0100000000050000001402000000000500000014029402 2903050000002e01010000001f000000320a940229030d000400000000002a10cc0d656163682073746f72696e67200025002500250029001500200017002a001c0017002a0029001500050000002e0100000000050000001402000000000500000014029402d204050000002e010100000011000000320a9402d2040400 0400000000002a10cc0d6f6e65202a00290025001500050000002e01000000000500000014020000000005000000140294025f05050000002e010100000011000000320a94025f0504000400000000002a10cc0d737569742100290017001700050000002e01000000000500000014020000000005000000020101000000 05000000020101000000050000001402f6024a01050000002e010100000028000000320af6024a0113000400000000002a10cc0d6c656e6774687320636f6d62696e6174696f6e031700250029002a0017002a002000150025002b003f002a00180029002500170017002a002900050000002e0100000000050000001402 0000000005000000020101000000040000002701ffff1000000026060f001600ffffffff0000430100009a03000078020000cf04000008000000fa0200000600000000000000040000002d010500040000002d010600080000002503020073029e0373019e04040000002d01030004000000f001050007000000fc020000 000000000000040000002d0105000a000000240303005e0185044701ca048c01b304040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff0100040000002d0100000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057006f007200640044006f0063007500 6d0065006e007400000000000000000000000000000000000000000000000000000000000000000000000000000000001a000200070000000a000000ffffffff0000000000000000000000000000000000000000000000000000000000000000000000003d0000001e140000000000005200690063006800450064006900 740046006c0061006700730000000000000000000000000000000000000000000000000000000000000000000000000000001c000200ffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000040000000c000000000000000500530075006d006d006100 7200790049006e0066006f0072006d006100740069006f006e00000000000000000000000000000000000000000000000000000028000201090000000b000000ffffffff000000000000000000000000000000000000000000000000000000000000000000000000480000000010000000000000050044006f0063007500 6d0065006e007400530075006d006d0061007200790049006e0066006f0072006d006100740069006f006e000000000000000000000038000200ffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000500000000010000000000000eca5c10059001d04 00000012bf000000000000100000000000040000210700000e00626a626af357f3570000000000000000000000000000000000001d0416001e140000913d0100913d0100260000000000000000000000000000000000000000000000fa02000000000000ffff0f000000000000000000ffff0f000000000000000000ffff 0f00000000000000000000000000000000005d00000000009800000000000000980000009800000000000000980000000000000048040000000000004804000000000000480400001400000000000000000000007804000000000000780400000000000078040000000000007804000000000000780400000c0000008404 0000140000007804000000000000201a0000b6000000a404000000000000a404000000000000a404000000000000a404000000000000a4040000000000001b160000000000001b160000000000001b16000000000000e519000002000000e719000000000000e719000000000000e719000000000000e719000000000000 e719000000000000e719000024000000d61a0000f4010000ca1c0000520000000b1a0000150000000000000000000000000000000000000048040000000000001b1600000000000000000000000000000000000000000000c11100005a0400001b160000000000001b160000000000001b160000000000000b1a00000000 0000e51900000000000098000000000000009800000000000000a4040000000000000000000000000000a40400001d0d0000a404000000000000e519000000000000e519000000000000e5190000000000001b160000ca03000098000000a8020000a4040000000000004804000000000000a404000000000000e5190000 00000000000000000000000000000000000000005c0400000e0000006a0400000e00000098000000000000009800000000000000980000000000000098000000000000001b16000000000000e519000000000000e519000000000000e5190000000000000000000000000000e51900000000000040030000080100004804 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e519000000000000a404000000000000980400000c00000040a7f1f91886c80178040000000000007804000000000000e519000000000000e519000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000080808080808080808080808080808080808080808080808080808080808080808080808080d57696e6e696e67206361726473206e6f646573206561636820636f6e7461696e696e6720616c6c2077696e6e696e6720636172647320666f72206f6e6520737569742e20497420706f696e747320746f 20616e20616c7465726e61746976652077696e6e696e67206361726473206e6f64652c20746f20746865206e6578742072657175697265642077696e6e696e67206361726473206e6f646520666f7220746865206e657874207375697420696e20746869732074726565206272616e636820616e6420746f206120736574 206f6620706f736974696f6e73206e6f6465206966206974206973207468652077696e6e696e6720636172647320206e6f646520666f7220746865206c61737420737569742e2e200d0d57696e0d0d57696e0d0d57696e0d0d57696e0d0d57696e0d0d536574206f6620706f736974696f6e732028534f5029206e6f6465 7320636f6e7461696e696e672074686520706f736974696f6e7320757070657220616e64206c6f7765722076616c756520626f756e642e200d0d0d57696e0d0d534f500d0d526f6f7420706f696e7465720d0d526f6f7420706f696e7465720d0d4120706f696e74657220706572206e6f206f6620747269636b73206c65 667420616e6420706572206c656164696e672068616e642e20506f696e747320746f2074686520726f6f74206f6620697473207472656520636f6e73697374696e67206f662073756974206c656e6774687320636f6d62696e6174696f6e206e6f6465732e0d456163682073756974206c656e6774687320636f6d62696e 6174696f6e206e6f646520706f696e747320746f2074686520726f6f74206f66206974732077696e6e696e67206361726420747265652e0d0d57696e0d0d57696e0d0d534f500d0d534f500d0d416c742e0d0d416c742e0d0d416c742e0d0d4e6578740d0d4e6578740d0d4e6578740d0d4e6578740d0d0d54726565206f 66206e6f64657320656163682073746f72696e67206f6e652073756974206c656e6774687320636f6d62696e6174696f6e0d0d0d0d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000400002504000021070000f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000d036a000000005508016d480004000200040000260400003d0500003e050000420500004305000047050000480500004c0500004d05000051050000520500005605000057050000ab050000ac050000ad050000b1050000b2050000b605 0000b7050000c4050000c5050000d2050000d305000056060000a6060000a7060000ab060000ac060000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd0000000000 00000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd00 0000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd00000000000000000000 0000fd000000000000000000000000fd000000000000000000000000fd00000000000000000000000000000000000000000000010000001d00040000260400003d0500003e050000420500004305000047050000480500004c0500004d05000051050000520500005605000057050000ab050000ac050000ad050000b105 0000b2050000b6050000b7050000c4050000c5050000d2050000d305000056060000a6060000a7060000ab060000ac060000b0060000b1060000b5060000b6060000ba060000bb060000c0060000c1060000c6060000c7060000cc060000cd060000d2060000d3060000d8060000d9060000de060000df060000e4060000 e5060000e60600001e0700001f0700002007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035ac060000b0060000b1060000b5060000b6060000ba060000bb060000c0060000c1060000c6060000c7060000cc060000cd060000d2060000d3060000d806 0000d9060000de060000df060000e4060000e5060000e60600001e0700001f0700002007000021070000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd0000000000 00000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd00 0000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd000000000000000000000000fd0000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000191c001fb0cc4e20b0c04e21b0001422b001142390d2162490d21625b00000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000feff0000060002000000000000000000000000000000000001000000e0859ff2f94f6810ab9108002b27b3d93000 0000580100001000000001000000880000000200000090000000030000009c00000004000000a800000005000000bc00000007000000c800000008000000d800000009000000ec00000012000000f80000000a000000140100000c000000200100000d0000002c0100000e000000380100000f0000004001000010000000 48010000130000005001000002000000e40400001e00000001000000000073001e00000001000000000073001e0000000b000000426f204861676c756e6400001e00000001000000006f20481e000000070000004e6f726d616c00751e0000000b000000426f204861676c756e6400001e00000002000000320020481e00 0000130000004d6963726f736f667420576f726420382e3000004000000000000000000000004000000000f475e11886c8014000000000f475e11886c80103000000010000000300000000000000030000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000feff000006000200000000000000000000000000000000000200000002d5cdd59c2e1b10939708002b2cf9ae4400000005d5cdd59c2e1b10939708002b2cf9ae2c010000e80000000c00000001000000680000000f00000070000000050000007c0000000600000084000000 110000008c00000017000000940000000b0000009c00000010000000a400000013000000ac00000016000000b40000000d000000bc0000000c000000c900000002000000e40400001e0000000200000020000000030000000100000003000000010000000300000000000000030000006a1008000b000000000000000b00 0000000000000b000000000000000b000000000000001e1000000100000001000000000c100000020000001e000000060000005469746c6500030000000100000000980000000300000000000000200000000100000036000000020000003e00000001000000020000000a0000005f5049445f475549440002000000e404 0000410000004e0000007b00340038003700430043003500330038002d0041004100460038002d0034003800390031002d0041003500440046002d003200410037003700460032004400340034003800340046007d0000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001050000050000000d0000004d45544146494c4550494354006d44000099c5ffffce3e000008006d44673a0000 010009000003631f000008003100000000001400000026060f001e00ffffffff040014000000576f72640e004d6963726f736f667420576f7264050000000b0200000000050000000c02cc0d2a101c000000fb021000070000000000bc02000000000102022253797374656d0000640e666f00000a0022008a0100000000 ffffffff48d41200040000002d010000050000000201010000001c000000fb02adff0000000000009001000000000440001254696d6573204e657720526f6d616e0030cb120010da1c76c0601f76640e666f040000002d010100050000000902000000000500000002010100000007000000fc020000ffffff0000000400 00002d01020008000000fa0200000600000000000002040000002d010300070000001b042703580f1a00b70907000000fc020000ffffff000000040000002d01040004000000f001020008000000fa0200000000000000000000040000002d01020004000000f0010300030000001e000700000016040503190f3b00f609 050000000201010000000500000014023c00f609050000002e010100000020000000320a3c00f6090e000400000000002a10cc0d4120706f696e74657220706572203b0015002a002a0017002900170025001c0015002a0025001c001500050000002e0100000000050000001402000000000500000014023c00c70b0500 00002e01010000001f000000320a3c00c70b0d000400000000002a10cc0d6e6f206f6620747269636b73200029002a0015002a001b00150017001c00170025002a0020001500050000002e0100000000050000001402000000000500000014023c00570d050000002e01010000001d000000320a3c00570d0c0004000000 00002a10cc0d6c65667420616e6420706572170025001c0017001500250029002a0015002a0025001c00050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014029c00f609050000002e010100000020000000320a9c00f6090e000400000000002a10cc0d6c65 6164696e672068616e642e201700250025002a0017002900290016002900250029002a0015001500050000002e0100000000050000001402000000000500000014029c00cb0b050000002e010100000020000000320a9c00cb0b0e000400000000002a10cc0d506f696e747320746f20746865202f002a00170029001700 2000150017002a0015001800290025001500050000002e0100000000050000001402000000000500000014029c00810d050000002e010100000017000000320a9c00810d08000400000000002a10cc0d726f6f74206f66201c002a002a00170015002a001b001500050000002e0100000000050000001402000000000500 000014029c00770e050000002e010100000010000000320a9c00770e03000400000000002a10cc0d69747300170017002000050000002e0100000000050000001402000000000500000002010100000005000000020101000000050000001402fc00f609050000002e010100000013000000320afc00f609050004000000 00002a10cc0d74726565200017001c00250025001500050000002e010000000005000000140200000000050000001402fc00880a050000002e010100000020000000320afc00880a0e000400000000002a10cc0d636f6e73697374696e67206f662025002a002900200017002000170018002a00290015002a001b001500 050000002e010000000005000000140200000000050000001402fc00480c050000002e010100000013000000320afc00480c05000400000000002a10cc0d73756974200021002900170017001500050000002e010000000005000000140200000000050000001402fc00d50c050000002e010100000016000000320afc00 d50c07000400000000002a10cc0d6c656e6774687320170026002a00290017002a002000050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014025c01f609050000002e01010000001d000000320a5c01f6090c000400000000002a10cc0d636f6d62696e6174 696f6e2025002a003f002a00180029002500170017002b0029001500050000002e0100000000050000001402000000000500000014025c01ab0b050000002e010100000014000000320a5c01ab0b06000400000000002a10cc0d6e6f6465732e29002a002a00250020001500050000002e01000000000500000014020000 00000500000002010100000005000000020101000000050000001402bb01f609050000002e010100000013000000320abb01f60905000400000000002a10cc0d45616368200033002500250029001500050000002e010000000005000000140200000000050000001402bb01b10a050000002e010100000013000000320a bb01b10a05000400000000002a10cc0d73756974200020002a00170017001500050000002e010000000005000000140200000000050000001402bb013e0b050000002e010100000029000000320abb013e0b14000400000000002a10cc0d6c656e6774687320636f6d62696e6174696f6e20170025002a00290018002900 2000150025002b003f002b00170029002500170017002b0029001500050000002e010000000005000000140200000000050000001402bb01f90d050000002e010100000011000000320abb01f90d04000400000000002a10cc0d6e6f646529002a002a002500050000002e01000000000500000014020000000005000000 020101000000050000000201010000000500000014021b02f609050000002e010100000020000000320a1b02f6090e000400000000002a10cc0d706f696e747320746f20746865202a002a001700290017002000150017002a0015001700290025001500050000002e010000000005000000140200000000050000001402 1b02a60b050000002e010100000017000000320a1b02a60b08000400000000002a10cc0d726f6f74206f66201c002a002a00170015002a001b001500050000002e0100000000050000001402000000000500000014021b029c0c050000002e010100000011000000320a1b029c0c04000400000000002a10cc0d69747320 1700170020001600050000002e0100000000050000001402000000000500000014021b02000d050000002e010100000017000000320a1b02000d08000400000000002a10cc0d77696e6e696e67203b00180029002a001700290029001500050000002e0100000000050000001402000000000500000014021b02240e0500 00002e010100000011000000320a1b02240e04000400000000002a10cc0d63617264260025001c002a00050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014027d02f609050000002e010100000013000000320a7d02f60905000400000000002a10cc0d7472 65652e0017001c00250025001500050000002e01000000000500000014020000000005000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01030008000000fa0200000600000000000002040000002d010500070000001b04d707d00fca04b709040000002d01040004000000f001 0300040000002d01020004000000f0010500030000001e00070000001604b507910feb04f60905000000020101000000040000002d01010005000000090200000000050000001402ec04f609050000002e010100000017000000320aec04f60908000400000000002a10cc0d57696e6e696e67204f001700290029001800 2a0029001500050000002e01000000000500000014020902640e050000001402ec042e0b050000002e010100000014000000320aec042e0b06000400000000002a10cc0d636172647320250025001c002a0020001500050000002e010000000005000000140200000000050000001402ec04f30b050000002e0101000000 14000000320aec04f30b06000400000000002a10cc0d6e6f6465732029002a002a00250020001500050000002e010000000005000000140200000000050000001402ec04ca0c050000002e010100000013000000320aec04ca0c05000400000000002a10cc0d65616368200025002500250029001500050000002e010000 000005000000140200000000050000001402ec04770d050000002e010100000020000000320aec04770d0e000400000000002a10cc0d636f6e7461696e696e6720616c6c25002a002900170026001700290018002a0029001500250017001700050000002e01000000000500000014020000000005000000020101000000 050000000201010000000500000014024c05f609050000002e010100000017000000320a4c05f60908000400000000002a10cc0d77696e6e696e67203b0018002a0029001800290029001500050000002e0100000000050000001402000000000500000014024c051b0b050000002e01010000001a000000320a4c051b0b 0a000400000000002a10cc0d636172647320666f7220250025001c002a00200015001b002a001c001500050000002e0100000000050000001402000000000500000014024c05560c050000002e010100000011000000320a4c05560c04000400000000002a10cc0d6f6e65202a00290025001500050000002e0100000000 050000001402000000000500000014024c05e30c050000002e010100000019000000320a4c05e30c09000400000000002a10cc0d737569742e20497420202100290017001700150015001c0017001500050000002e0100000000050000001402000000000500000014024c05cd0d050000002e01010000001d000000320a 4c05cd0d0c000400000000002a10cc0d706f696e747320746f20616e2a002a001700290017002000150017002a00150026002900050000002e0100000000050000001402000000000500000002010100000005000000020101000000050000001402ac05f609050000002e01010000001d000000320aac05f6090c000400 000000002a10cc0d616c7465726e61746976652025001700170025001c002900250017001800290025001600050000002e010000000005000000140200000000050000001402ac056b0b050000002e010100000017000000320aac056b0b08000400000000002a10cc0d77696e6e696e67203b0018002900290018002a00 29001500050000002e010000000005000000140200000000050000001402ac05900c050000002e010100000014000000320aac05900c06000400000000002a10cc0d636172647320250025001c002a0020001500050000002e010000000005000000140200000000050000001402ac05550d050000002e01010000001f00 0000320aac05550d0d000400000000002a10cc0d6e6f64652c20746f20746865200029002a002a0025001500150017002a0015001700290025001500050000002e010000000005000000140200000000050000001402ac05f10e050000002e010100000011000000320aac05f10e04000400000000002a10cc0d6e657874 290025002a001700050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014020c06f609050000002e010100000019000000320a0c06f60909000400000000002a10cc0d726571756972656420201c0025002a00290017001c0025002a001600050000002e010000 0000050000001402000000000500000014020c06220b050000002e010100000017000000320a0c06220b08000400000000002a10cc0d77696e6e696e67203a0017002a00290018002a0029001500050000002e0100000000050000001402000000000500000014020c06460c050000002e010100000014000000320a0c06 460c06000400000000002a10cc0d636172647320250025001c002a0020001500050000002e0100000000050000001402000000000500000014020c060b0d050000002e01010000001f000000320a0c060b0d0d000400000000002a10cc0d6e6f646520666f7220746865200029002a002a00250015001b002a001c001500 1700290025001500050000002e0100000000050000001402000000000500000014020c06b20e050000002e010100000011000000320a0c06b20e04000400000000002a10cc0d6e6578742900260029001700050000002e010000000005000000140200000000050000000201010000000500000002010100000005000000 14026b06f609050000002e010100000017000000320a6b06f60908000400000000002a10cc0d7375697420696e2020002900170017001500180029001500050000002e0100000000050000001402000000000500000014026b06d80a050000002e010100000013000000320a6b06d80a05000400000000002a10cc0d7468 6973200018002900170020001500050000002e0100000000050000001402000000000500000014026b06650b050000002e010100000013000000320a6b06650b05000400000000002a10cc0d74726565200017001c00250025001500050000002e0100000000050000001402000000000500000014026b06f70b05000000 2e01010000002c000000320a6b06f70b16000400000000002a10cc0d6272616e636820616e6420746f206120736574206f662a001c0025002900260029001500250029002a00150017002a0015002500150020002500170015002a001b00050000002e010000000005000000140200000000050000000201010000000500 0000020101000000050000001402cb06f609050000002e01010000001a000000320acb06f6090a000400000000002a10cc0d706f736974696f6e73202a002a0020001700170017002a00290020001600050000002e010000000005000000140200000000050000001402cb06380b050000002e010100000013000000320a cb06380b05000400000000002a10cc0d6e6f6465200029002a002a0025001500050000002e010000000005000000140200000000050000001402cb06ef0b050000002e01010000001f000000320acb06ef0b0d000400000000002a10cc0d696620697420697320746865200017001b001500170017001500170020001500 1800290025001600050000002e010000000005000000140200000000050000001402cb06410d050000002e010100000017000000320acb06410d08000400000000002a10cc0d77696e6e696e67203b0018002900290018002a0029001500050000002e010000000005000000140200000000050000001402cb06660e0500 00002e010100000013000000320acb06660e05000400000000002a10cc0d636172647300250025001c002a002000050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014022d07f609050000002e010100000026000000320a2d07f60912000400000000002a10 cc0d6e6f646520666f7220746865206c6173742029002a002a00250015001b002a001c001500170029002500150017002500200017001500050000002e0100000000050000001402000000000500000014022d07250c050000002e010100000014000000320a2d07250c06000400000000002a10cc0d737569742e2e2100 29001700170015001500050000002e01000000000500000014020000000005000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01030008000000fa0200000600000000000002040000002d010500070000001b048301380256009300040000002d01040004000000f00103000400 00002d01020004000000f0010500030000001e000700000016046101f9017700d20005000000020101000000040000002d010100050000000902000000000500000014027800d200050000002e010100000011000000320a7800d20004000400000000002a10cc0d526f6f7437002a002a001700050000002e0100000000 0500000014020902640e0500000002010100000005000000020101000000050000001402da00d200050000002e010100000016000000320ada00d20007000400000000002a10cc0d706f696e746572002a002a0017002900170025001c00050000002e010000000005000000140200000000050000000201010000000400 00002701ffff07000000fc020000ffffff000000040000002d01030008000000fa0200000600000000000002040000002d010500070000001b048301340656005304040000002d01040004000000f0010300040000002d01020004000000f0010500030000001e000700000016046101f505770092040500000002010100 0000040000002d0101000500000009020000000005000000140278009204050000002e010100000011000000320a7800920404000400000000002a10cc0d526f6f7437002a002a001700050000002e01000000000500000014020902640e0500000002010100000005000000020101000000050000001402da0092040500 00002e010100000016000000320ada00920407000400000000002a10cc0d706f696e746572002a002a0017002900170025001c00050000002e01000000000500000014020000000005000000020101000000040000002701ffff1000000026060f001600ffffffff0000ab020000ca000000e0030000d300000008000000 fa0205000100000000000000040000002d01030007000000fc020000000000000000040000002d010500050000000601020000002800000024031200b002cb00af02cb00ae02cc00ad02cd00ac02ce00ac02ce00ad02cf00ae02d000af02d100af02d100af02d100b002d000b102cf00b202ce00b202ce00b102cd00b002 cc00b002cb002800000024031200bb02cb00ba02cb00b902cc00b802cd00b802ce00b802cf00b802d000b902d100ba02d100bb02d100bb02d100bc02d000bd02cf00be02ce00be02ce00bd02cd00bc02cc00bc02cb002800000024031200c702cb00c602cb00c502cc00c402cd00c402ce00c402cf00c402d000c502d100 c602d100c702d100c702d100c802d000c902cf00ca02ce00ca02ce00c902cd00c802cc00c802cb002800000024031200d302cb00d202cb00d102cc00d002cd00d002ce00d002cf00d002d000d102d100d202d100d302d100d302d100d402d000d502cf00d602ce00d602ce00d502cd00d402cc00d402cb00280000002403 1200df02cb00de02cb00dd02cc00dc02cd00dc02ce00dc02cf00dc02d000dd02d100de02d100df02d100df02d100e002d000e102cf00e202ce00e202ce00e102cd00e002cc00e002cb002800000024031200eb02cb00ea02cb00e902cc00e802cd00e802ce00e802cf00e802d000e902d100ea02d100eb02d100eb02d100 ec02d000ed02cf00ee02ce00ee02ce00ed02cd00ec02cc00ec02cb002800000024031200f702cb00f602cb00f502cc00f402cd00f402ce00f402cf00f402d000f502d100f602d100f702d100f702d100f802d000f902cf00fa02ce00fa02ce00f902cd00f802cc00f802cb0028000000240312000303cb000203cb000103 cc000003cd000003ce000003cf000003d0000103d1000203d1000303d1000303d1000403d0000503cf000603ce000603ce000503cd000403cc000403cb0028000000240312000f03cb000e03cb000d03cc000c03cd000c03ce000c03cf000c03d0000d03d1000e03d1000f03d1000f03d1001003d0001103cf001203ce00 1203ce001103cd001003cc001003cb0028000000240312001b03cb001a03cb001903cc001803cd001803ce001803cf001803d0001903d1001a03d1001b03d1001b03d1001c03d0001d03cf001e03ce001e03ce001d03cd001c03cc001c03cb0028000000240312002703cb002603cb002503cc002403cd002403ce002403 cf002403d0002503d1002603d1002703d1002703d1002803d0002903cf002a03ce002a03ce002903cd002803cc002803cb0028000000240312003303cb003203cb003103cc003003cd003003ce003003cf003003d0003103d1003203d1003303d1003303d1003403d0003503cf003603ce003603ce003503cd003403cc00 3403cb0028000000240312003f03cb003e03cb003d03cc003c03cd003c03ce003c03cf003c03d0003d03d1003e03d1003f03d1003f03d1004003d0004103cf004203ce004203ce004103cd004003cc004003cb0028000000240312004b03cb004a03cb004903cc004803cd004803ce004803cf004803d0004903d1004a03 d1004b03d1004b03d1004c03d0004d03cf004e03ce004e03ce004d03cd004c03cc004c03cb0028000000240312005703cb005603cb005503cc005403cd005403ce005403cf005403d0005503d1005603d1005703d1005703d1005803d0005903cf005a03ce005a03ce005903cd005803cc005803cb002800000024031200 6303cb006203cb006103cc006003cd006003ce006003cf006003d0006103d1006203d1006303d1006303d1006403d0006503cf006603ce006603ce006503cd006403cc006403cb0028000000240312006f03cb006e03cb006d03cc006c03cd006c03ce006c03cf006c03d0006d03d1006e03d1006f03d1006f03d1007003 d0007103cf007203ce007203ce007103cd007003cc007003cb0028000000240312007b03cb007a03cb007903cc007803cd007803ce007803cf007803d0007903d1007a03d1007b03d1007b03d1007c03d0007d03cf007e03ce007e03ce007d03cd007c03cc007c03cb0028000000240312008703cb008603cb008503cc00 8403cd008403ce008403cf008403d0008503d1008603d1008703d1008703d1008803d0008903cf008a03ce008a03ce008903cd008803cc008803cb0028000000240312009303cb009203cb009103cc009003cd009003ce009003cf009003d0009103d1009203d1009303d1009303d1009403d0009503cf009603ce009603 ce009503cd009403cc009403cb0028000000240312009f03cb009e03cb009d03cc009c03cd009c03ce009c03cf009c03d0009d03d1009e03d1009f03d1009f03d100a003d000a103cf00a203ce00a203ce00a103cd00a003cc00a003cb002800000024031200ab03cb00aa03cb00a903cc00a803cd00a803ce00a803cf00 a803d000a903d100aa03d100ab03d100ab03d100ac03d000ad03cf00ae03ce00ae03ce00ad03cd00ac03cc00ac03cb002800000024031200b703cb00b603cb00b503cc00b403cd00b403ce00b403cf00b403d000b503d100b603d100b703d100b703d100b803d000b903cf00ba03ce00ba03ce00b903cd00b803cc00b803 cb002800000024031200c303cb00c203cb00c103cc00c003cd00c003ce00c003cf00c003d000c103d100c203d100c303d100c303d100c403d000c503cf00c603ce00c603ce00c503cd00c403cc00c403cb002800000024031200cf03cb00ce03cb00cd03cc00cc03cd00cc03ce00cc03cf00cc03d000cd03d100ce03d100 cf03d100cf03d100d003d000d103cf00d203ce00d203ce00d103cd00d003cc00d003cb0005000000060101000000040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff010007000000fc020000ffffff000000040000002d01050008000000fa02000006000000000000020400 00002d010600070000001b04bb05fc01ca04cf00040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e000700000016049905bd01eb040e0105000000020101000000040000002d01010005000000090200000000050000001402ee040e01050000002e010100000010000000320a ee040e0103000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b04bb050805ca04db030400 00002d01040004000000f0010500040000002d01020004000000f0010600030000001e000700000016049905c904eb041a0405000000020101000000040000002d01010005000000090200000000050000001402ee041a04050000002e010100000010000000320aee041a0403000400000000002a10cc0d57696e034f00 17002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b041308fc012207cf00040000002d01040004000000f0010500040000002d010200 04000000f0010600030000001e00070000001604f107bd0143070e0105000000020101000000040000002d0101000500000009020000000005000000140246070e01050000002e010100000010000000320a46070e0103000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902 640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b04130808052207db03040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604f107 c90443071a0405000000020101000000040000002d0101000500000009020000000005000000140246071a04050000002e010100000010000000320a46071a0403000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff0700 0000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b046b0afc017a09cf00040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604490abd019b090e0105000000020101000000040000002d01 0100050000000902000000000500000014029e090e01050000002e010100000010000000320a9e090e0103000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d0105000800 0000fa0200000600000000000002040000002d010600070000001b046b0a08057a09db03040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604490ac9049b091a0405000000020101000000040000002d010100050000000902000000000500000014029e091a04 050000002e010100000010000000320a9e091a0403000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600 070000001b04130814082207e706040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604f107d5074307260705000000020101000000040000002d0101000500000009020000000005000000140246072607050000002e010100000010000000320a460726070300 0400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b046b0a14087a09e706040000002d010400 04000000f0010500040000002d01020004000000f0010600030000001e00070000001604490ad5079b09260705000000020101000000040000002d010100050000000902000000000500000014029e092607050000002e010100000010000000320a9e09260703000400000000002a10cc0d57696e034f00170029000500 00002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b040f0cfc011e0bcf00040000002d01040004000000f0010500040000002d01020004000000f001 0600030000001e00070000001604ed0bbd013f0b0e0105000000020101000000040000002d01010005000000090200000000050000001402420b0e01050000002e010100000010000000320a420b0e0103000400000000002a10cc0d534f50032e003c002f00050000002e01000000000500000014020902640e05000000 020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b040f0c08051e0bdb03040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604ed0bc9043f0b1a04 05000000020101000000040000002d01010005000000090200000000050000001402420b1a04050000002e010100000010000000320a420b1a0403000400000000002a10cc0d534f50032e003c002f00050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000 ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b040f0c14081e0be706040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604ed0bd5073f0b260705000000020101000000040000002d01010005000000 090200000000050000001402420b2607050000002e010100000010000000320a420b260703000400000000002a10cc0d534f50032e003c002f00050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa020000 0600000000000002040000002d010600070000001b040f0c940f6a0af309040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604ed0b550f8b0a320a05000000020101000000040000002d010100050000000902000000000500000014028c0a320a050000002e01 0100000026000000320a8c0a320a12000400000000002a10cc0d536574206f6620706f736974696f6e7320282e002500170015002a001b0015002a002a0020001700170017002a002a00200015001c00050000002e01000000000500000014020902640e0500000014028c0a690c050000002e010100000013000000320a 8c0a690c05000400000000002a10cc0d534f502920002e003c002f001c001500050000002e0100000000050000001402000000000500000014028c0a330d050000002e010100000013000000320a8c0a330d05000400000000002a10cc0d6e6f6465730029002a002a0025002000050000002e0100000000050000001402 000000000500000002010100000005000000020101000000050000001402ec0a320a050000002e010100000031000000320aec0a320a19000400000000002a10cc0d636f6e7461696e696e672074686520706f736974696f6e73200025002a002900170025001700290018002a002900150017002900250015002a002a00 20001700180017002a00290020001600050000002e010000000005000000140200000000050000001402ec0a630d050000002e010100000019000000320aec0a630d09000400000000002a10cc0d757070657220616e642029002a002a0025001c001500250029002a00050000002e010000000005000000140200000000 05000000020101000000050000000201010000000500000014024c0b320a050000002e010100000014000000320a4c0b320a06000400000000002a10cc0d6c6f7765722017002b003a0025001c001500050000002e0100000000050000001402000000000500000014024c0b040b050000002e010100000014000000320a 4c0b040b06000400000000002a10cc0d76616c756520290025001800290025001500050000002e0100000000050000001402000000000500000014024c0bcd0b050000002e010100000014000000320a4c0bcd0b06000400000000002a10cc0d626f756e642e2a002a002a0029002a001500050000002e01000000000500 0000140200000000050000000201010000000500000002010100000005000000020101000000040000002701ffff1000000026060f001600ffffffff0000f70100007e010000b40200007702000008000000fa0200000600000000000000040000002d01050007000000fc020100000000000000040000002d0106000800 000025030200fb0182018a024002040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303006e025202af027202a2022b02040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff 0000f70100001e050000e00300006805000008000000fa0200000600000000000000040000002d010500040000002d0106000800000025030200fb0142059c034205040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303009a036305db0342059a0322050400 00002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff000022010000b60500006c0100002707000008000000fa0200000600000000000000040000002d010500040000002d01060008000000250302004701ba054701e306040000002d010300 04000000f001050007000000fc020000000000000000040000002d0105000a000000240303002601e106470122076701e106040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff0000f701000076070000e0030000c007000008000000 fa0200000600000000000000040000002d010500040000002d0106000800000025030200fb019a079c039a07040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303009a03bb07db039a079a037a07040000002d010200040000002d01040004000000f0010500 0800000026060f000600ffffffff01001000000026060f001600ffffffff00000305000076070000ec060000c007000008000000fa0200000600000000000000040000002d010500040000002d010600080000002503020007059a07a8069a07040000002d01030004000000f001050007000000fc020000000000000000 040000002d0105000a00000024030300a606bb07e7069a07a6067a07040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff0000220100000e0800006c0100007f09000008000000fa0200000600000000000000040000002d0105000400 00002d01060008000000250302004701120847013b09040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303002601390947017a0967013909040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff0100100000002606 0f001600ffffffff00002e0400000e080000780400007f09000008000000fa0200000600000000000000040000002d010500040000002d01060008000000250302005304120853043b09040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a00000024030300320439095304 7a0973043909040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff00003a0700000e080000840700007f09000008000000fa0200000600000000000000040000002d010500040000002d01060008000000250302005f0712085f073b09 040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303003e0739095f077a097f073909040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff000022010000660a00006c010000 230b000008000000fa0200000600000000000000040000002d010500040000002d010600080000002503020047016a0a4701df0a040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303002601dd0a47011e0b6701dd0a040000002d010200040000002d010400 04000000f00105000800000026060f000600ffffffff0100040000002d010600040000002d010300070000001b04bb056403ca043702040000002d010400040000002d010200030000001e000700000016049c052803e804730205000000020101000000040000002d01010005000000090200000000050000001402eb04 7302050000002e010100000011000000320aeb04730204000400000000002a10cc0d416c742e3b00170017001500050000002e01000000000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b041308640322073702040000002d01040004000000 2d010200030000001e00070000001604f40728034007730205000000020101000000040000002d0101000500000009020000000005000000140243077302050000002e010100000011000000320a4307730204000400000000002a10cc0d416c742e3b00170017001500050000002e01000000000500000014020902640e 05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b041308700622074305040000002d010400040000002d010200030000001e00070000001604f407340640077f0505000000020101000000040000002d0101000500000009020000000005000000140243077f0505000000 2e010100000011000000320a43077f0504000400000000002a10cc0d416c742e3b00170017001500050000002e01000000000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b04e7067402f6054701040000002d010400040000002d0102000300 00001e00070000001604c80638021406830105000000020101000000040000002d0101000500000009020000000005000000140217068301050000002e010100000011000000320a1706830104000400000000002a10cc0d4e6578743c00250029001700050000002e01000000000500000014020902640e050000000201 01000000040000002701ffff040000002d010600040000002d010300070000001b043f0974024e084701040000002d010400040000002d010200030000001e00070000001604200938026c08830105000000020101000000040000002d010100050000000902000000000500000014026f088301050000002e0101000000 11000000320a6f08830104000400000000002a10cc0d4e6578743c00250029001700050000002e01000000000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b043f0980054e085304040000002d010400040000002d010200030000001e000700 00001604200944056c088f0405000000020101000000040000002d010100050000000902000000000500000014026f088f04050000002e010100000011000000320a6f088f0404000400000000002a10cc0d4e6578743c00250029001700050000002e01000000000500000014020902640e050000000201010000000400 00002701ffff040000002d010600040000002d010300070000001b043f098c084e085f07040000002d010400040000002d010200030000001e00070000001604200950086c089b0705000000020101000000040000002d010100050000000902000000000500000014026f089b07050000002e010100000011000000320a 6f089b0704000400000000002a10cc0d4e6578743c00250029001700050000002e01000000000500000014020902640e05000000020101000000040000002701ffff1000000026060f001600ffffffff00002e040000660a000078040000230b000008000000fa0200000600000000000000040000002d01050004000000 2d010600080000002503020053046a0a5304df0a040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303003204dd0a53041e0b7304dd0a040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f00 1600ffffffff00003a070000660a000084070000230b000008000000fa0200000600000000000000040000002d010500040000002d01060008000000250302005f076a0a5f07df0a040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303003e07dd0a5f071e0b 7f07dd0a040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff010007000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010700070000001b049f03340672020b01040000002d01040004000000f0010500040000002d01 020004000000f0010700030000001e000700000016047d03f50593024a0105000000020101000000040000002d0101000500000009020000000005000000140294024a01050000002e010100000017000000320a94024a0108000400000000002a10cc0d54726565206f662034001c002500240015002a001b0015000500 00002e01000000000500000014020902640e05000000140294025202050000002e010100000014000000320a9402520206000400000000002a10cc0d6e6f6465732029002a002a00250020001500050000002e01000000000500000014020000000005000000140294022903050000002e01010000001f000000320a9402 29030d000400000000002a10cc0d656163682073746f72696e67200025002500250029001500200017002a001c0017002a0029001500050000002e0100000000050000001402000000000500000014029402d204050000002e010100000011000000320a9402d20404000400000000002a10cc0d6f6e65202a0029002500 1500050000002e01000000000500000014020000000005000000140294025f05050000002e010100000011000000320a94025f0504000400000000002a10cc0d737569742100290017001700050000002e0100000000050000001402000000000500000002010100000005000000020101000000050000001402f6024a01 050000002e010100000028000000320af6024a0113000400000000002a10cc0d6c656e6774687320636f6d62696e6174696f6e031700250029002a0017002a002000150025002b003f002a00180029002500170017002a002900050000002e01000000000500000014020000000005000000020101000000040000002701 ffff1000000026060f001600ffffffff0000430100009a03000078020000cf04000008000000fa0200000600000000000000040000002d010500040000002d010600080000002503020073029e0373019e04040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a0000002403 03005e0185044701ca048c01b304040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff0100040000002d010000030000000000}{\result {\f1\fs20\lang1053 {\pict{\*\picprop\shplid1025{\sp{\sn shapeType}{\sv 75}}{\sp{\sn fFlipH}{\sv 0}} {\sp{\sn fFlipV}{\sv 0}}{\sp{\sn pictureGray}{\sv 0}}{\sp{\sn pictureBiLevel}{\sv 0}}{\sp{\sn pictureActive}{\sv 0}}{\sp{\sn fillColor}{\sv 268435473}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fHitTestFill}{\sv 1}}{\sp{\sn fillShape}{\sv 1}} {\sp{\sn fillUseRect}{\sv 0}}{\sp{\sn fNoFillHitTest}{\sv 0}}{\sp{\sn fLine}{\sv 0}}}\picscalex98\picscaley98\piccropl0\piccropr0\piccropt0\piccropb0 \picw17517\pich14951\picwgoal9931\pichgoal8476\wmetafile8\bliptag21317130\blipupi-134{\*\blipuid 0145460ab0e156603b98478d583ea052} 010009000003631f000008003100000000001400000026060f001e00ffffffff040014000000576f72640e004d6963726f736f667420576f7264050000000b02 00000000050000000c02cc0d2a101c000000fb021000070000000000bc02000000000102022253797374656d0000640e666f00000a0022008a0100000000ffff ffff48d41200040000002d010000050000000201010000001c000000fb02adff0000000000009001000000000440001254696d6573204e657720526f6d616e00 30cb120010da1c76c0601f76640e666f040000002d010100050000000902000000000500000002010100000007000000fc020000ffffff000000040000002d01 020008000000fa0200000600000000000002040000002d010300070000001b042703580f1a00b70907000000fc020000ffffff000000040000002d0104000400 0000f001020008000000fa0200000000000000000000040000002d01020004000000f0010300030000001e000700000016040503190f3b00f609050000000201 010000000500000014023c00f609050000002e010100000020000000320a3c00f6090e000400000000002a10cc0d4120706f696e74657220706572203b001500 2a002a0017002900170025001c0015002a0025001c001500050000002e0100000000050000001402000000000500000014023c00c70b050000002e0101000000 1f000000320a3c00c70b0d000400000000002a10cc0d6e6f206f6620747269636b73200029002a0015002a001b00150017001c00170025002a00200015000500 00002e0100000000050000001402000000000500000014023c00570d050000002e01010000001d000000320a3c00570d0c000400000000002a10cc0d6c656674 20616e6420706572170025001c0017001500250029002a0015002a0025001c00050000002e010000000005000000140200000000050000000201010000000500 00000201010000000500000014029c00f609050000002e010100000020000000320a9c00f6090e000400000000002a10cc0d6c656164696e672068616e642e20 1700250025002a0017002900290016002900250029002a0015001500050000002e0100000000050000001402000000000500000014029c00cb0b050000002e01 0100000020000000320a9c00cb0b0e000400000000002a10cc0d506f696e747320746f20746865202f002a001700290017002000150017002a00150018002900 25001500050000002e0100000000050000001402000000000500000014029c00810d050000002e010100000017000000320a9c00810d08000400000000002a10 cc0d726f6f74206f66201c002a002a00170015002a001b001500050000002e0100000000050000001402000000000500000014029c00770e050000002e010100 000010000000320a9c00770e03000400000000002a10cc0d69747300170017002000050000002e01000000000500000014020000000005000000020101000000 05000000020101000000050000001402fc00f609050000002e010100000013000000320afc00f60905000400000000002a10cc0d74726565200017001c002500 25001500050000002e010000000005000000140200000000050000001402fc00880a050000002e010100000020000000320afc00880a0e000400000000002a10 cc0d636f6e73697374696e67206f662025002a002900200017002000170018002a00290015002a001b001500050000002e010000000005000000140200000000 050000001402fc00480c050000002e010100000013000000320afc00480c05000400000000002a10cc0d73756974200021002900170017001500050000002e01 0000000005000000140200000000050000001402fc00d50c050000002e010100000016000000320afc00d50c07000400000000002a10cc0d6c656e6774687320 170026002a00290017002a002000050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014025c01f609 050000002e01010000001d000000320a5c01f6090c000400000000002a10cc0d636f6d62696e6174696f6e2025002a003f002a00180029002500170017002b00 29001500050000002e0100000000050000001402000000000500000014025c01ab0b050000002e010100000014000000320a5c01ab0b06000400000000002a10 cc0d6e6f6465732e29002a002a00250020001500050000002e010000000005000000140200000000050000000201010000000500000002010100000005000000 1402bb01f609050000002e010100000013000000320abb01f60905000400000000002a10cc0d45616368200033002500250029001500050000002e0100000000 05000000140200000000050000001402bb01b10a050000002e010100000013000000320abb01b10a05000400000000002a10cc0d73756974200020002a001700 17001500050000002e010000000005000000140200000000050000001402bb013e0b050000002e010100000029000000320abb013e0b14000400000000002a10 cc0d6c656e6774687320636f6d62696e6174696f6e20170025002a002900180029002000150025002b003f002b00170029002500170017002b00290015000500 00002e010000000005000000140200000000050000001402bb01f90d050000002e010100000011000000320abb01f90d04000400000000002a10cc0d6e6f6465 29002a002a002500050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014021b02f609050000002e01 0100000020000000320a1b02f6090e000400000000002a10cc0d706f696e747320746f20746865202a002a001700290017002000150017002a00150017002900 25001500050000002e0100000000050000001402000000000500000014021b02a60b050000002e010100000017000000320a1b02a60b08000400000000002a10 cc0d726f6f74206f66201c002a002a00170015002a001b001500050000002e0100000000050000001402000000000500000014021b029c0c050000002e010100 000011000000320a1b029c0c04000400000000002a10cc0d697473201700170020001600050000002e0100000000050000001402000000000500000014021b02 000d050000002e010100000017000000320a1b02000d08000400000000002a10cc0d77696e6e696e67203b00180029002a001700290029001500050000002e01 00000000050000001402000000000500000014021b02240e050000002e010100000011000000320a1b02240e04000400000000002a10cc0d6361726426002500 1c002a00050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014027d02f609050000002e0101000000 13000000320a7d02f60905000400000000002a10cc0d747265652e0017001c00250025001500050000002e010000000005000000140200000000050000000201 01000000040000002701ffff07000000fc020000ffffff000000040000002d01030008000000fa0200000600000000000002040000002d010500070000001b04 d707d00fca04b709040000002d01040004000000f0010300040000002d01020004000000f0010500030000001e00070000001604b507910feb04f60905000000 020101000000040000002d01010005000000090200000000050000001402ec04f609050000002e010100000017000000320aec04f60908000400000000002a10 cc0d57696e6e696e67204f0017002900290018002a0029001500050000002e01000000000500000014020902640e050000001402ec042e0b050000002e010100 000014000000320aec042e0b06000400000000002a10cc0d636172647320250025001c002a0020001500050000002e0100000000050000001402000000000500 00001402ec04f30b050000002e010100000014000000320aec04f30b06000400000000002a10cc0d6e6f6465732029002a002a00250020001500050000002e01 0000000005000000140200000000050000001402ec04ca0c050000002e010100000013000000320aec04ca0c05000400000000002a10cc0d6561636820002500 2500250029001500050000002e010000000005000000140200000000050000001402ec04770d050000002e010100000020000000320aec04770d0e0004000000 00002a10cc0d636f6e7461696e696e6720616c6c25002a002900170026001700290018002a0029001500250017001700050000002e0100000000050000001402 0000000005000000020101000000050000000201010000000500000014024c05f609050000002e010100000017000000320a4c05f60908000400000000002a10 cc0d77696e6e696e67203b0018002a0029001800290029001500050000002e0100000000050000001402000000000500000014024c051b0b050000002e010100 00001a000000320a4c051b0b0a000400000000002a10cc0d636172647320666f7220250025001c002a00200015001b002a001c001500050000002e0100000000 050000001402000000000500000014024c05560c050000002e010100000011000000320a4c05560c04000400000000002a10cc0d6f6e65202a00290025001500 050000002e0100000000050000001402000000000500000014024c05e30c050000002e010100000019000000320a4c05e30c09000400000000002a10cc0d7375 69742e20497420202100290017001700150015001c0017001500050000002e0100000000050000001402000000000500000014024c05cd0d050000002e010100 00001d000000320a4c05cd0d0c000400000000002a10cc0d706f696e747320746f20616e2a002a001700290017002000150017002a0015002600290005000000 2e0100000000050000001402000000000500000002010100000005000000020101000000050000001402ac05f609050000002e01010000001d000000320aac05 f6090c000400000000002a10cc0d616c7465726e61746976652025001700170025001c002900250017001800290025001600050000002e010000000005000000 140200000000050000001402ac056b0b050000002e010100000017000000320aac056b0b08000400000000002a10cc0d77696e6e696e67203b00180029002900 18002a0029001500050000002e010000000005000000140200000000050000001402ac05900c050000002e010100000014000000320aac05900c060004000000 00002a10cc0d636172647320250025001c002a0020001500050000002e010000000005000000140200000000050000001402ac05550d050000002e0101000000 1f000000320aac05550d0d000400000000002a10cc0d6e6f64652c20746f20746865200029002a002a0025001500150017002a00150017002900250015000500 00002e010000000005000000140200000000050000001402ac05f10e050000002e010100000011000000320aac05f10e04000400000000002a10cc0d6e657874 290025002a001700050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014020c06f609050000002e01 0100000019000000320a0c06f60909000400000000002a10cc0d726571756972656420201c0025002a00290017001c0025002a001600050000002e0100000000 050000001402000000000500000014020c06220b050000002e010100000017000000320a0c06220b08000400000000002a10cc0d77696e6e696e67203a001700 2a00290018002a0029001500050000002e0100000000050000001402000000000500000014020c06460c050000002e010100000014000000320a0c06460c0600 0400000000002a10cc0d636172647320250025001c002a0020001500050000002e0100000000050000001402000000000500000014020c060b0d050000002e01 010000001f000000320a0c060b0d0d000400000000002a10cc0d6e6f646520666f7220746865200029002a002a00250015001b002a001c001500170029002500 1500050000002e0100000000050000001402000000000500000014020c06b20e050000002e010100000011000000320a0c06b20e04000400000000002a10cc0d 6e6578742900260029001700050000002e01000000000500000014020000000005000000020101000000050000000201010000000500000014026b06f6090500 00002e010100000017000000320a6b06f60908000400000000002a10cc0d7375697420696e2020002900170017001500180029001500050000002e0100000000 050000001402000000000500000014026b06d80a050000002e010100000013000000320a6b06d80a05000400000000002a10cc0d746869732000180029001700 20001500050000002e0100000000050000001402000000000500000014026b06650b050000002e010100000013000000320a6b06650b05000400000000002a10 cc0d74726565200017001c00250025001500050000002e0100000000050000001402000000000500000014026b06f70b050000002e01010000002c000000320a 6b06f70b16000400000000002a10cc0d6272616e636820616e6420746f206120736574206f662a001c0025002900260029001500250029002a00150017002a00 15002500150020002500170015002a001b00050000002e0100000000050000001402000000000500000002010100000005000000020101000000050000001402 cb06f609050000002e01010000001a000000320acb06f6090a000400000000002a10cc0d706f736974696f6e73202a002a0020001700170017002a0029002000 1600050000002e010000000005000000140200000000050000001402cb06380b050000002e010100000013000000320acb06380b05000400000000002a10cc0d 6e6f6465200029002a002a0025001500050000002e010000000005000000140200000000050000001402cb06ef0b050000002e01010000001f000000320acb06 ef0b0d000400000000002a10cc0d696620697420697320746865200017001b0015001700170015001700200015001800290025001600050000002e0100000000 05000000140200000000050000001402cb06410d050000002e010100000017000000320acb06410d08000400000000002a10cc0d77696e6e696e67203b001800 2900290018002a0029001500050000002e010000000005000000140200000000050000001402cb06660e050000002e010100000013000000320acb06660e0500 0400000000002a10cc0d636172647300250025001c002a002000050000002e010000000005000000140200000000050000000201010000000500000002010100 00000500000014022d07f609050000002e010100000026000000320a2d07f60912000400000000002a10cc0d6e6f646520666f7220746865206c617374202900 2a002a00250015001b002a001c001500170029002500150017002500200017001500050000002e0100000000050000001402000000000500000014022d07250c 050000002e010100000014000000320a2d07250c06000400000000002a10cc0d737569742e2e210029001700170015001500050000002e010000000005000000 14020000000005000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01030008000000fa02000006000000000000020400 00002d010500070000001b048301380256009300040000002d01040004000000f0010300040000002d01020004000000f0010500030000001e00070000001604 6101f9017700d20005000000020101000000040000002d010100050000000902000000000500000014027800d200050000002e010100000011000000320a7800 d20004000400000000002a10cc0d526f6f7437002a002a001700050000002e01000000000500000014020902640e050000000201010000000500000002010100 0000050000001402da00d200050000002e010100000016000000320ada00d20007000400000000002a10cc0d706f696e746572002a002a001700290017002500 1c00050000002e01000000000500000014020000000005000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d0103000800 0000fa0200000600000000000002040000002d010500070000001b048301340656005304040000002d01040004000000f0010300040000002d01020004000000 f0010500030000001e000700000016046101f5057700920405000000020101000000040000002d01010005000000090200000000050000001402780092040500 00002e010100000011000000320a7800920404000400000000002a10cc0d526f6f7437002a002a001700050000002e01000000000500000014020902640e0500 000002010100000005000000020101000000050000001402da009204050000002e010100000016000000320ada00920407000400000000002a10cc0d706f696e 746572002a002a0017002900170025001c00050000002e01000000000500000014020000000005000000020101000000040000002701ffff1000000026060f00 1600ffffffff0000ab020000ca000000e0030000d300000008000000fa0205000100000000000000040000002d01030007000000fc0200000000000000000400 00002d010500050000000601020000002800000024031200b002cb00af02cb00ae02cc00ad02cd00ac02ce00ac02ce00ad02cf00ae02d000af02d100af02d100 af02d100b002d000b102cf00b202ce00b202ce00b102cd00b002cc00b002cb002800000024031200bb02cb00ba02cb00b902cc00b802cd00b802ce00b802cf00 b802d000b902d100ba02d100bb02d100bb02d100bc02d000bd02cf00be02ce00be02ce00bd02cd00bc02cc00bc02cb002800000024031200c702cb00c602cb00 c502cc00c402cd00c402ce00c402cf00c402d000c502d100c602d100c702d100c702d100c802d000c902cf00ca02ce00ca02ce00c902cd00c802cc00c802cb00 2800000024031200d302cb00d202cb00d102cc00d002cd00d002ce00d002cf00d002d000d102d100d202d100d302d100d302d100d402d000d502cf00d602ce00 d602ce00d502cd00d402cc00d402cb002800000024031200df02cb00de02cb00dd02cc00dc02cd00dc02ce00dc02cf00dc02d000dd02d100de02d100df02d100 df02d100e002d000e102cf00e202ce00e202ce00e102cd00e002cc00e002cb002800000024031200eb02cb00ea02cb00e902cc00e802cd00e802ce00e802cf00 e802d000e902d100ea02d100eb02d100eb02d100ec02d000ed02cf00ee02ce00ee02ce00ed02cd00ec02cc00ec02cb002800000024031200f702cb00f602cb00 f502cc00f402cd00f402ce00f402cf00f402d000f502d100f602d100f702d100f702d100f802d000f902cf00fa02ce00fa02ce00f902cd00f802cc00f802cb00 28000000240312000303cb000203cb000103cc000003cd000003ce000003cf000003d0000103d1000203d1000303d1000303d1000403d0000503cf000603ce00 0603ce000503cd000403cc000403cb0028000000240312000f03cb000e03cb000d03cc000c03cd000c03ce000c03cf000c03d0000d03d1000e03d1000f03d100 0f03d1001003d0001103cf001203ce001203ce001103cd001003cc001003cb0028000000240312001b03cb001a03cb001903cc001803cd001803ce001803cf00 1803d0001903d1001a03d1001b03d1001b03d1001c03d0001d03cf001e03ce001e03ce001d03cd001c03cc001c03cb0028000000240312002703cb002603cb00 2503cc002403cd002403ce002403cf002403d0002503d1002603d1002703d1002703d1002803d0002903cf002a03ce002a03ce002903cd002803cc002803cb00 28000000240312003303cb003203cb003103cc003003cd003003ce003003cf003003d0003103d1003203d1003303d1003303d1003403d0003503cf003603ce00 3603ce003503cd003403cc003403cb0028000000240312003f03cb003e03cb003d03cc003c03cd003c03ce003c03cf003c03d0003d03d1003e03d1003f03d100 3f03d1004003d0004103cf004203ce004203ce004103cd004003cc004003cb0028000000240312004b03cb004a03cb004903cc004803cd004803ce004803cf00 4803d0004903d1004a03d1004b03d1004b03d1004c03d0004d03cf004e03ce004e03ce004d03cd004c03cc004c03cb0028000000240312005703cb005603cb00 5503cc005403cd005403ce005403cf005403d0005503d1005603d1005703d1005703d1005803d0005903cf005a03ce005a03ce005903cd005803cc005803cb00 28000000240312006303cb006203cb006103cc006003cd006003ce006003cf006003d0006103d1006203d1006303d1006303d1006403d0006503cf006603ce00 6603ce006503cd006403cc006403cb0028000000240312006f03cb006e03cb006d03cc006c03cd006c03ce006c03cf006c03d0006d03d1006e03d1006f03d100 6f03d1007003d0007103cf007203ce007203ce007103cd007003cc007003cb0028000000240312007b03cb007a03cb007903cc007803cd007803ce007803cf00 7803d0007903d1007a03d1007b03d1007b03d1007c03d0007d03cf007e03ce007e03ce007d03cd007c03cc007c03cb0028000000240312008703cb008603cb00 8503cc008403cd008403ce008403cf008403d0008503d1008603d1008703d1008703d1008803d0008903cf008a03ce008a03ce008903cd008803cc008803cb00 28000000240312009303cb009203cb009103cc009003cd009003ce009003cf009003d0009103d1009203d1009303d1009303d1009403d0009503cf009603ce00 9603ce009503cd009403cc009403cb0028000000240312009f03cb009e03cb009d03cc009c03cd009c03ce009c03cf009c03d0009d03d1009e03d1009f03d100 9f03d100a003d000a103cf00a203ce00a203ce00a103cd00a003cc00a003cb002800000024031200ab03cb00aa03cb00a903cc00a803cd00a803ce00a803cf00 a803d000a903d100aa03d100ab03d100ab03d100ac03d000ad03cf00ae03ce00ae03ce00ad03cd00ac03cc00ac03cb002800000024031200b703cb00b603cb00 b503cc00b403cd00b403ce00b403cf00b403d000b503d100b603d100b703d100b703d100b803d000b903cf00ba03ce00ba03ce00b903cd00b803cc00b803cb00 2800000024031200c303cb00c203cb00c103cc00c003cd00c003ce00c003cf00c003d000c103d100c203d100c303d100c303d100c403d000c503cf00c603ce00 c603ce00c503cd00c403cc00c403cb002800000024031200cf03cb00ce03cb00cd03cc00cc03cd00cc03ce00cc03cf00cc03d000cd03d100ce03d100cf03d100 cf03d100d003d000d103cf00d203ce00d203ce00d103cd00d003cc00d003cb0005000000060101000000040000002d010200040000002d01040004000000f001 05000800000026060f000600ffffffff010007000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600 070000001b04bb05fc01ca04cf00040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e000700000016049905bd01eb04 0e0105000000020101000000040000002d01010005000000090200000000050000001402ee040e01050000002e010100000010000000320aee040e0103000400 000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000 ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b04bb050805ca04db03040000002d01040004000000 f0010500040000002d01020004000000f0010600030000001e000700000016049905c904eb041a0405000000020101000000040000002d010100050000000902 00000000050000001402ee041a04050000002e010100000010000000320aee041a0403000400000000002a10cc0d57696e034f0017002900050000002e010000 00000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa02000006000000 00000002040000002d010600070000001b041308fc012207cf00040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00 070000001604f107bd0143070e0105000000020101000000040000002d0101000500000009020000000005000000140246070e01050000002e01010000001000 0000320a46070e0103000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e0500000002010100000004000000 2701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b04130808052207db03 040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604f107c90443071a04050000000201010000000400 00002d0101000500000009020000000005000000140246071a04050000002e010100000010000000320a46071a0403000400000000002a10cc0d57696e034f00 17002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d010500 08000000fa0200000600000000000002040000002d010600070000001b046b0afc017a09cf00040000002d01040004000000f0010500040000002d0102000400 0000f0010600030000001e00070000001604490abd019b090e0105000000020101000000040000002d010100050000000902000000000500000014029e090e01 050000002e010100000010000000320a9e090e0103000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e0500 0000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d0106000700 00001b046b0a08057a09db03040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604490ac9049b091a04 05000000020101000000040000002d010100050000000902000000000500000014029e091a04050000002e010100000010000000320a9e091a04030004000000 00002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffff ff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b04130814082207e706040000002d01040004000000f001 0500040000002d01020004000000f0010600030000001e00070000001604f107d5074307260705000000020101000000040000002d0101000500000009020000 000005000000140246072607050000002e010100000010000000320a4607260703000400000000002a10cc0d57696e034f0017002900050000002e0100000000 0500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa020000060000000000 0002040000002d010600070000001b046b0a14087a09e706040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e000700 00001604490ad5079b09260705000000020101000000040000002d010100050000000902000000000500000014029e092607050000002e010100000010000000 320a9e09260703000400000000002a10cc0d57696e034f0017002900050000002e01000000000500000014020902640e05000000020101000000040000002701 ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b040f0cfc011e0bcf000400 00002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604ed0bbd013f0b0e010500000002010100000004000000 2d01010005000000090200000000050000001402420b0e01050000002e010100000010000000320a420b0e0103000400000000002a10cc0d534f50032e003c00 2f00050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff000000040000002d0105000800 0000fa0200000600000000000002040000002d010600070000001b040f0c08051e0bdb03040000002d01040004000000f0010500040000002d01020004000000 f0010600030000001e00070000001604ed0bc9043f0b1a0405000000020101000000040000002d01010005000000090200000000050000001402420b1a040500 00002e010100000010000000320a420b1a0403000400000000002a10cc0d534f50032e003c002f00050000002e01000000000500000014020902640e05000000 020101000000040000002701ffff07000000fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d01060007000000 1b040f0c14081e0be706040000002d01040004000000f0010500040000002d01020004000000f0010600030000001e00070000001604ed0bd5073f0b26070500 0000020101000000040000002d01010005000000090200000000050000001402420b2607050000002e010100000010000000320a420b26070300040000000000 2a10cc0d534f50032e003c002f00050000002e01000000000500000014020902640e05000000020101000000040000002701ffff07000000fc020000ffffff00 0000040000002d01050008000000fa0200000600000000000002040000002d010600070000001b040f0c940f6a0af309040000002d01040004000000f0010500 040000002d01020004000000f0010600030000001e00070000001604ed0b550f8b0a320a05000000020101000000040000002d01010005000000090200000000 0500000014028c0a320a050000002e010100000026000000320a8c0a320a12000400000000002a10cc0d536574206f6620706f736974696f6e7320282e002500 170015002a001b0015002a002a0020001700170017002a002a00200015001c00050000002e01000000000500000014020902640e0500000014028c0a690c0500 00002e010100000013000000320a8c0a690c05000400000000002a10cc0d534f502920002e003c002f001c001500050000002e01000000000500000014020000 00000500000014028c0a330d050000002e010100000013000000320a8c0a330d05000400000000002a10cc0d6e6f6465730029002a002a002500200005000000 2e0100000000050000001402000000000500000002010100000005000000020101000000050000001402ec0a320a050000002e010100000031000000320aec0a 320a19000400000000002a10cc0d636f6e7461696e696e672074686520706f736974696f6e73200025002a002900170025001700290018002a00290015001700 2900250015002a002a0020001700180017002a00290020001600050000002e010000000005000000140200000000050000001402ec0a630d050000002e010100 000019000000320aec0a630d09000400000000002a10cc0d757070657220616e642029002a002a0025001c001500250029002a00050000002e01000000000500 000014020000000005000000020101000000050000000201010000000500000014024c0b320a050000002e010100000014000000320a4c0b320a060004000000 00002a10cc0d6c6f7765722017002b003a0025001c001500050000002e0100000000050000001402000000000500000014024c0b040b050000002e0101000000 14000000320a4c0b040b06000400000000002a10cc0d76616c756520290025001800290025001500050000002e01000000000500000014020000000005000000 14024c0bcd0b050000002e010100000014000000320a4c0bcd0b06000400000000002a10cc0d626f756e642e2a002a002a0029002a001500050000002e010000 000005000000140200000000050000000201010000000500000002010100000005000000020101000000040000002701ffff1000000026060f001600ffffffff 0000f70100007e010000b40200007702000008000000fa0200000600000000000000040000002d01050007000000fc020100000000000000040000002d010600 0800000025030200fb0182018a024002040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303006e02 5202af027202a2022b02040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff 0000f70100001e050000e00300006805000008000000fa0200000600000000000000040000002d010500040000002d0106000800000025030200fb0142059c03 4205040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303009a036305db0342059a03220504000000 2d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff000022010000b60500006c010000 2707000008000000fa0200000600000000000000040000002d010500040000002d01060008000000250302004701ba054701e306040000002d01030004000000 f001050007000000fc020000000000000000040000002d0105000a000000240303002601e106470122076701e106040000002d010200040000002d0104000400 0000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff0000f701000076070000e0030000c007000008000000fa0200000600 000000000000040000002d010500040000002d0106000800000025030200fb019a079c039a07040000002d01030004000000f001050007000000fc0200000000 00000000040000002d0105000a000000240303009a03bb07db039a079a037a07040000002d010200040000002d01040004000000f00105000800000026060f00 0600ffffffff01001000000026060f001600ffffffff00000305000076070000ec060000c007000008000000fa0200000600000000000000040000002d010500 040000002d010600080000002503020007059a07a8069a07040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a00 000024030300a606bb07e7069a07a6067a07040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff0100100000002606 0f001600ffffffff0000220100000e0800006c0100007f09000008000000fa0200000600000000000000040000002d010500040000002d010600080000002503 02004701120847013b09040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303002601390947017a09 67013909040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff00002e040000 0e080000780400007f09000008000000fa0200000600000000000000040000002d010500040000002d01060008000000250302005304120853043b0904000000 2d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000240303003204390953047a0973043909040000002d0102000400 00002d01040004000000f00105000800000026060f000600ffffffff01001000000026060f001600ffffffff00003a0700000e080000840700007f0900000800 0000fa0200000600000000000000040000002d010500040000002d01060008000000250302005f0712085f073b09040000002d01030004000000f00105000700 0000fc020000000000000000040000002d0105000a000000240303003e0739095f077a097f073909040000002d010200040000002d01040004000000f0010500 0800000026060f000600ffffffff01001000000026060f001600ffffffff000022010000660a00006c010000230b000008000000fa0200000600000000000000 040000002d010500040000002d010600080000002503020047016a0a4701df0a040000002d01030004000000f001050007000000fc0200000000000000000400 00002d0105000a000000240303002601dd0a47011e0b6701dd0a040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff 0100040000002d010600040000002d010300070000001b04bb056403ca043702040000002d010400040000002d010200030000001e000700000016049c052803 e804730205000000020101000000040000002d01010005000000090200000000050000001402eb047302050000002e010100000011000000320aeb0473020400 0400000000002a10cc0d416c742e3b00170017001500050000002e01000000000500000014020902640e05000000020101000000040000002701ffff04000000 2d010600040000002d010300070000001b041308640322073702040000002d010400040000002d010200030000001e00070000001604f4072803400773020500 0000020101000000040000002d0101000500000009020000000005000000140243077302050000002e010100000011000000320a430773020400040000000000 2a10cc0d416c742e3b00170017001500050000002e01000000000500000014020902640e05000000020101000000040000002701ffff040000002d0106000400 00002d010300070000001b041308700622074305040000002d010400040000002d010200030000001e00070000001604f407340640077f050500000002010100 0000040000002d0101000500000009020000000005000000140243077f05050000002e010100000011000000320a43077f0504000400000000002a10cc0d416c 742e3b00170017001500050000002e01000000000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300 070000001b04e7067402f6054701040000002d010400040000002d010200030000001e00070000001604c8063802140683010500000002010100000004000000 2d0101000500000009020000000005000000140217068301050000002e010100000011000000320a1706830104000400000000002a10cc0d4e6578743c002500 29001700050000002e01000000000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b04 3f0974024e084701040000002d010400040000002d010200030000001e00070000001604200938026c08830105000000020101000000040000002d0101000500 00000902000000000500000014026f088301050000002e010100000011000000320a6f08830104000400000000002a10cc0d4e6578743c002500290017000500 00002e01000000000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b043f0980054e08 5304040000002d010400040000002d010200030000001e00070000001604200944056c088f0405000000020101000000040000002d0101000500000009020000 00000500000014026f088f04050000002e010100000011000000320a6f088f0404000400000000002a10cc0d4e6578743c00250029001700050000002e010000 00000500000014020902640e05000000020101000000040000002701ffff040000002d010600040000002d010300070000001b043f098c084e085f0704000000 2d010400040000002d010200030000001e00070000001604200950086c089b0705000000020101000000040000002d0101000500000009020000000005000000 14026f089b07050000002e010100000011000000320a6f089b0704000400000000002a10cc0d4e6578743c00250029001700050000002e010000000005000000 14020902640e05000000020101000000040000002701ffff1000000026060f001600ffffffff00002e040000660a000078040000230b000008000000fa020000 0600000000000000040000002d010500040000002d010600080000002503020053046a0a5304df0a040000002d01030004000000f001050007000000fc020000 000000000000040000002d0105000a000000240303003204dd0a53041e0b7304dd0a040000002d010200040000002d01040004000000f0010500080000002606 0f000600ffffffff01001000000026060f001600ffffffff00003a070000660a000084070000230b000008000000fa0200000600000000000000040000002d01 0500040000002d01060008000000250302005f076a0a5f07df0a040000002d01030004000000f001050007000000fc020000000000000000040000002d010500 0a000000240303003e07dd0a5f071e0b7f07dd0a040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff010007000000 fc020000ffffff000000040000002d01050008000000fa0200000600000000000002040000002d010700070000001b049f03340672020b01040000002d010400 04000000f0010500040000002d01020004000000f0010700030000001e000700000016047d03f50593024a0105000000020101000000040000002d0101000500 000009020000000005000000140294024a01050000002e010100000017000000320a94024a0108000400000000002a10cc0d54726565206f662034001c002500 240015002a001b001500050000002e01000000000500000014020902640e05000000140294025202050000002e010100000014000000320a9402520206000400 000000002a10cc0d6e6f6465732029002a002a00250020001500050000002e01000000000500000014020000000005000000140294022903050000002e010100 00001f000000320a940229030d000400000000002a10cc0d656163682073746f72696e67200025002500250029001500200017002a001c0017002a0029001500 050000002e0100000000050000001402000000000500000014029402d204050000002e010100000011000000320a9402d20404000400000000002a10cc0d6f6e 65202a00290025001500050000002e01000000000500000014020000000005000000140294025f05050000002e010100000011000000320a94025f0504000400 000000002a10cc0d737569742100290017001700050000002e010000000005000000140200000000050000000201010000000500000002010100000005000000 1402f6024a01050000002e010100000028000000320af6024a0113000400000000002a10cc0d6c656e6774687320636f6d62696e6174696f6e03170025002900 2a0017002a002000150025002b003f002a00180029002500170017002a002900050000002e010000000005000000140200000000050000000201010000000400 00002701ffff1000000026060f001600ffffffff0000430100009a03000078020000cf04000008000000fa0200000600000000000000040000002d0105000400 00002d010600080000002503020073029e0373019e04040000002d01030004000000f001050007000000fc020000000000000000040000002d0105000a000000 240303005e0185044701ca048c01b304040000002d010200040000002d01040004000000f00105000800000026060f000600ffffffff0100040000002d0100000300000000000000000000000000000000000000000000000000}}}}}{\lang1053 \par The \'94suit lengths combination\'94 node includes: \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls14\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls14\adjustright {\lang1053 The suit lengths combination as a 64-bit integer. \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls14\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls14\adjustright {\lang1053 A pointer to the top \'94 winning cards node\'94. \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls14\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls14\adjustright {\lang1053 A pointer to next left \'94 suit lengths combination node\'94 in the binary tree. \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls14\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls14\adjustright {\lang1053 A pointer to next right \'94 suit lengths combination node\'94 in the binary tree. \par }\pard \nowidctlpar\adjustright {\lang1053 \par \par The \'94winning cards node\'94 includes: \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-720\li720\nowidctlpar{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3 {\pntxtb \'b7}}\ls4\adjustright {\lang1053 The hands of the relative ranks for each winning card of the actual suit. \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-720\li720\nowidctlpar{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3 {\pntxtb \'b7}}\ls4\adjustright {\lang1053 A pointer to the next winning cards node required to achieve a Transposition Table match for this branch of the tree. \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-720\li720\nowidctlpar{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3 {\pntxtb \'b7}}\ls4\adjustright {\lang1053 A pointer to the previous winning cards node. \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-720\li720\nowidctlpar{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3 {\pntxtb \'b7}}\ls4\adjustright {\lang1053 A pointer to the next alternative winning cards n ode that leads to a Transposition Table match in an alternative tree branch. \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li360\nowidctlpar\jclisttab\tx360{\*\pn \pnlvlblt\ilvl0\ls10\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls10\adjustright {\lang1053 A pointer to the "set of positions node". \par }\pard \nowidctlpar\adjustright {\lang1053 \par \par The "set of positions node\'94 includes: \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-720\li720\nowidctlpar{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3 {\pntxtb \'b7}}\ls4\adjustright {\lang1053 An upper and a lower bound for the winning tricks of the North/South side. These values\line are used to determine whether or not a search cutoff can be done. \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-720\li720\nowidctlpar{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3 {\pntxtb \'b7}}\ls4\adjustright {\lang1053 The lowest winning rank per suit, expressed as relative rank. \par {\pntext\pard\plain\f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-720\li720\nowidctlpar{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3 {\pntxtb \'b7}}\ls4\adjustright {\lang1053 The suit and rank for the currently best move. \par }\pard \nowidctlpar\adjustright {\lang1053 \par \par }\pard \nowidctlpar\tx420\adjustright {\cf1\lang1053 After a Transposition Table match, the current position may later be part of a position that will be stored in the Transposition Table. Therefore, the stored winning ranks in the Transposition Table must be included in the state information of the current position. However, the winning ranks cannot be taken as is, because they are stored as relative ranks which now must be converted to absolute ranks in the current position. \par This is done using the lowest winning relative rank for each suit that is stored in the \'94set of positions\'94 node that gave the Transposition Table match: \par The aggregated set of (absolute) ranks for each suit in the current position is filtered using the stored information on the lowest winning relative rank. The winning ranks for each suit is then the aggregated set with only the number of highest ranks implied by the stored lowest winning relative rank in the \'94set of positions\'94 node. \par E.g. if the aggregated rank set for spades is A J 9 4 2 and lowest winning relative rank is order=2, then winning ranks are A J. \par }\pard \nowidctlpar\adjustright {\lang1053 \par \par }\pard \nowidctlpar\tx420\adjustright {\b\cf1\lang1053 7.4 Building a new entry in the Transposition Table}{\cf1\lang1053 \par \par When the value of the current position is known and it is the end of a trick (except the last), position state information is collected for storage in the Transposition Table. \par The ranks of the backed up winning cards are converted from absolute to relative. \par For each suit, it is determined which winning rank that is lowest. The relative ranks then stored in the new Transposition Table entry are all ranks above and including the lowest rank, filling out any \'94holes\'94 in the ranks that might have been present. \par The trees of the Transposition Table are searched starting from the \'94root pointer\'94 and additional nodes are inserted corresponding to the current position. \par First, the suit lengths of the current position are used to find a \'94suit lengths combination node\'94 or to create a new such node if it does not exist already. \par The next step is to search for a \'94winning card node\'94 that has the \'94suit length combination node\'94 as parent. This \'94winning card node\'94 has then winning cards for spades. \par If no such node yet exists, \'94winning card nodes\'94, one for each suit, are created using the winning cards of the current position. Each such node includes all winning cards for one of the suits. Then, a \'94set of positions\'94 node is created. This node is pointed to from the last created \'94winning card node\'94 created for the winning cards of clubs. \par Otherwise, if there already exists a matching \'94winning card node\'94 with the \'94suit length combination node\'94 as parent, it is checked whether or not the \'94winning card nodes\'94 in a subsequent tree branch already created for hearts, diamonds and clubs also are matched with the current position. \par If such a sequence of nodes can be found, the upper or lower bound in the connected \'94set of positions node\'94 may be updated to allow for an increased number of cutoffs: \par \par If the current position upper value bound is less than the stored upper value bound, the stored value is updated with the current position value. \par If the current position lower value bound is larger than the stored lower value bound, the stored value is updated with the current position value. \par \par In case a matching \'94winning card node\'94 cannot be found, a new \'94winning card node\'94 is created and linked to the last matching node. E.g. if existing \'94winning card nodes\'94 for spades and hearts match the current position, but no node match for diamonds, then a \'94winning cards node\'94 for diamonds is created and linked to the previous \'94winning cards node\'94 for hearts. Then a clubs \'94winning cards node\'94 and a \'94set of positions node\'94 are created. \par \par \par }\pard \nowidctlpar\adjustright {\b\lang1053 \par \par \par References \par }{\lang1053 \par James Dow Allen: \par Source code for a simple DDS. \par }{\field\fldedit{\*\fldinst {\lang1053 HYPERLINK \\l "_Hlk134153111" }{\fs20\lang1053 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0048006c006b00310033003400310035003300310031003100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000}}}{\fldrslt {\cs15\ul\cf2 http://freepages.genealogy.rootsweb.com/~jamesdow/Tech/dbldum.htm}}}{\lang1053 \par \par Matthias Brill: \par DDS algorithms description (in German) and DDS source code. \par }{\field\fldedit{\*\fldinst {\lang1053 HYPERLINK \\l "_Hlk134153080" }{\fs20\lang1053 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0048006c006b00310033003400310035003300300038003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000}}}{\fldrslt {\ul\cf2 http://linux.softpedia.com/get/Science-and-Engineering/Artificial-Intelligence/cddsolve-20055.shtml}{\lang1053 }}}{\lang1053 \par \par Ming-Sheng Chang: \par DDS algorithms description. \par {\*\bkmkstart _Hlt193293965}}{\field\fldedit{\*\fldinst {\lang1053 HYPERLINK "\\\\l "_Hlk132979785" "}{\fs20\lang1053 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b02000000010000000303000000000000c0000000000000460000040000005c6c2000ffffadde000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000}}}{\fldrslt {cs.nyu.edu/web/Research/TechReports/TR1996-725/TR1996-725.ps.gz \par }}}\pard\plain \nowidctlpar\adjustright \lang2057 {\lang1053 {\*\bkmkend _Hlt193293965} \par \par Ed Colley: \par DDS source code and DDS executable. \par }{\field\flddirty{\*\fldinst {\lang1053 HYPERLINK "\\\\l "_Hlk133040134" "}{\fs20\lang1053 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b02000000010000000303000000000000c0000000000000460000040000005c6c2000ffffadde000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000}}}{\fldrslt {\ul\cf2\lang1053 http://freefinesse.sourceforge.net/}}}{\lang1053 \par \par Matthew L. Ginsberg: \par DDS algorithms description. \par }{\field\fldedit{\*\fldinst {\lang1053 HYPERLINK \\l "_Hlk134152954" }{\fs20\lang1053 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0048006c006b00310033003400310035003200390035003400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000}}}{\fldrslt {\cs15\ul\cf2 http://www.cs.cmu.edu/afs/cs/project/jair/pub/volume14/ginsberg01a.pdf}}}{\lang1053 \par \par Dan Hirschberg: \par DDS algorithms description and DDS executable (MS DOS, cannot run in XP?) \par }{\field\flddirty{\*\fldinst {\lang1053 HYPERLINK "\\\\l "_Hlk132979763" "}{\fs20\lang1053 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b02000000010000000303000000000000c0000000000000460000040000005c6c2000ffffadde000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000}}}{\fldrslt {\ul\cf2\lang1053 http://www.ics.uci.edu/~dan/bridge/index.html \par }}}\pard\plain \nowidctlpar\adjustright \lang2057 {\lang1053 \par Alexey Slovesnov: \par DDS source code and DDS executable. \par \par Judea Pearl: Asymptotic properties of minimax trees and game search precedures.\line Artificial Intelligence 14(2):113-138. [Pearl 1980] \par \par Aske Plaat, Jonathan Schaeffer, Wim Pijls and Arie de Bruin: Exploiting graph properties of game trees. In }{\i\lang1053 Proceedings of the Thirteenth National Conference on Artificial Intelligence}{\lang1053 , pages 234-239, 1996 [Plaat et al.] \par \par Hans Kuijf, personal communication. \par \par Pedja Stanojevic, personal communication. \par \par Knuth: The art of computer programming, Vol. 3, Searching and Sorting, chapter 6.2.2, Algorithm T. \par \par Sebastian Kupferschmid, Malte Helmert: A Skat Player Based on Monte Carlo Simulation. \par \par Jo\'ebl Bradmetz, personal communication. \par http://jibe-bridge.perso.cegetel.net/ \par }}dds-2.4.2+ddd105/Makefile0000664000401600040160000000062512215416111012745 0ustar cbecbeCFLAGS=-g -Wall -O2 -std=c99 -fopenmp PREFIX=/usr/local all: libdds.a python dds.h: ln -s dll.h dds.h dds.c: ln -s dds.cpp $@ dds.o: dds.c dds.h libdds.a: dds.o ar rc $@ $^ ranlib $@ install: install -d $(DESTDIR)$(PREFIX)/include $(DESTDIR)$(PREFIX)/lib install -m644 dll.h $(DESTDIR)$(PREFIX)/include/dds.h install libdds.a $(DESTDIR)$(PREFIX)/lib clean: rm -f dds.o libdds.a dds.c dds.h