~ubuntu-branches/ubuntu/trusty/dds/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/dds.cpp-itoa/dds.cpp

  • Committer: Package Import Robot
  • Author(s): Christoph Berg
  • Date: 2014-01-21 16:23:21 UTC
  • mfrom: (1.1.9)
  • mto: This revision was merged to the branch mainline in revision 17.
  • Revision ID: package-import@ubuntu.com-20140121162321-a89w87amhqe3t573
New dds upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
/* DDS 2.3.0   A bridge double dummy solver.                                  */
3
 
/* Copyright (C) 2006-2012 by Bo Haglund                                      */
4
 
/* Cleanups and porting to Linux and MacOSX (C) 2006 by Alex Martelli.        */
5
 
/* The code for calculation of par score / contracts is based upon the        */
6
 
/* perl code written by Matthew Kidd for ACBLmerge. He has kindly given me    */
7
 
/* permission to include a C++ adaptation in DDS.                             */ 
8
 
/*                                                                            */
9
 
/* Licensed under the Apache License, Version 2.0 (the "License");            */
10
 
/* you may not use this file except in compliance with the License.           */
11
 
/* You may obtain a copy of the License at                                    */
12
 
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
13
 
/* Unless required by applicable law or agreed to in writing, software        */
14
 
/* distributed under the License is distributed on an "AS IS" BASIS,          */
15
 
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
16
 
/* See the License for the specific language governing permissions and        */
17
 
/* limitations under the License.                                             */
18
 
 
19
 
 
20
 
/*#include "stdafx.h"*/         /* Needed by Visual C++ */
21
 
 
22
 
#include "dll.h"
23
 
 
24
 
struct localVarType localVar[MAXNOOFTHREADS];
25
 
 
26
 
int * counttable;
27
 
int * highestRank;
28
 
int lho[4];
29
 
int rho[4];
30
 
int partner[4];
31
 
unsigned short int bitMapRank[16];
32
 
unsigned char cardRank[15];
33
 
unsigned char cardSuit[5];
34
 
unsigned char cardHand[4];
35
 
int stat_contr[5]={0,0,0,0,0};
36
 
int max_low[3][8];  /* index 1: 0=NT, 1=Major, 2=Minor  index 2: contract level 1-7 */
37
 
 
38
 
struct ttStoreType * ttStore;
39
 
int lastTTstore;
40
 
int ttCollect;
41
 
int suppressTTlog;
42
 
 
43
 
int noOfThreads=MAXNOOFTHREADS;  /* The number of entries to the transposition tables. There is
44
 
                                    one entry per thread. */
45
 
int noOfCores;                  /* The number of processor cores, however cannot be higher than noOfThreads. */
46
 
 
47
 
#ifdef _MANAGED
48
 
#pragma managed(push, off)
49
 
#endif
50
 
 
51
 
 
52
 
#if defined(_WIN32)
53
 
extern "C" BOOL APIENTRY DllMain(HMODULE hModule,
54
 
                                DWORD ul_reason_for_call,
55
 
                                LPVOID lpReserved) {
56
 
  int k;
57
 
 
58
 
  if (ul_reason_for_call==DLL_PROCESS_ATTACH) {
59
 
    InitStart(0, 0);
60
 
  }
61
 
  else if (ul_reason_for_call==DLL_PROCESS_DETACH) {
62
 
    for (k=0; k<noOfThreads; k++) {
63
 
      Wipe(k);
64
 
      if (localVar[k].pw[0])
65
 
        free(localVar[k].pw[0]);
66
 
      localVar[k].pw[0]=NULL;
67
 
      if (localVar[k].pn[0])
68
 
        free(localVar[k].pn[0]);
69
 
      localVar[k].pn[0]=NULL;
70
 
      if (localVar[k].pl[0])
71
 
        free(localVar[k].pl[0]);
72
 
      localVar[k].pl[0]=NULL;
73
 
      if (localVar[k].pw)
74
 
        free(localVar[k].pw);
75
 
      localVar[k].pw=NULL;
76
 
      if (localVar[k].pn)
77
 
        free(localVar[k].pn);
78
 
      localVar[k].pn=NULL;
79
 
      if (localVar[k].pl)
80
 
        free(localVar[k].pl);
81
 
      localVar[k].pl=NULL;
82
 
      if (localVar[k].rel)
83
 
        free(localVar[k].rel);
84
 
      localVar[k].rel=NULL;
85
 
      if (localVar[k].adaptWins)
86
 
        free(localVar[k].adaptWins);
87
 
      localVar[k].adaptWins=NULL;
88
 
    }
89
 
    if (ttStore)
90
 
      free(ttStore);
91
 
    ttStore=NULL;
92
 
    if (highestRank)
93
 
      free(highestRank);
94
 
    highestRank=NULL;
95
 
    if (counttable)
96
 
      free(counttable);
97
 
    counttable=NULL;
98
 
        /*_CrtDumpMemoryLeaks();*/      /* MEMORY LEAK? */
99
 
  }
100
 
  return 1;
101
 
}
102
 
#endif
103
 
 
104
 
#ifdef _MANAGED
105
 
#pragma managed(pop)
106
 
#endif
107
 
 
108
 
  int STDCALL SolveBoard(struct deal dl, int target,
109
 
    int solutions, int mode, struct futureTricks *futp, int thrId) {
110
 
 
111
 
  int k, n, cardCount, found, totalTricks, tricks, last, checkRes;
112
 
  int g, upperbound, lowerbound, first, i, j, h, forb, ind, flag, noMoves;
113
 
  int mcurr;
114
 
  int noStartMoves;
115
 
  int handRelFirst;
116
 
  int noOfCardsPerHand[4];
117
 
  int latestTrickSuit[4];
118
 
  int latestTrickRank[4];
119
 
  int maxHand=0, maxSuit=0, maxRank;
120
 
  unsigned short int aggrRemain;
121
 
  struct movePlyType temp;
122
 
  struct moveType mv;
123
 
  int hiwinSetSize=0, hinodeSetSize=0;
124
 
  int hilenSetSize=0;
125
 
  int MaxnodeSetSize=0;
126
 
  int MaxwinSetSize=0;
127
 
  int MaxlenSetSize=0;
128
 
 
129
 
 
130
 
  /*InitStart(0,0);*/   /* Include InitStart() if inside SolveBoard,
131
 
                           but preferable InitStart should be called outside
132
 
                                         SolveBoard like in DllMain for Windows. */
133
 
 
134
 
  if ((thrId<0)||(thrId>=noOfThreads)) {        /* Fault corrected after suggestion by Dirk Willecke. */
135
 
    DumpInput(-15, dl, target, solutions, mode);
136
 
        return -15;
137
 
  }
138
 
 
139
 
  for (k=0; k<=13; k++) {
140
 
    localVar[thrId].forbiddenMoves[k].rank=0;
141
 
    localVar[thrId].forbiddenMoves[k].suit=0;
142
 
  }
143
 
 
144
 
  if (target<-1) {
145
 
    DumpInput(-5, dl, target, solutions, mode);
146
 
    return -5;
147
 
  }
148
 
  if (target>13) {
149
 
    DumpInput(-7, dl, target, solutions, mode);
150
 
    return -7;
151
 
  }
152
 
  if (solutions<1) {
153
 
    DumpInput(-8, dl, target, solutions, mode);
154
 
    return -8;
155
 
  }
156
 
  if (solutions>3) {
157
 
    DumpInput(-9, dl, target, solutions, mode);
158
 
    return -9;
159
 
  }
160
 
 
161
 
  for (k=0; k<=3; k++)
162
 
    noOfCardsPerHand[handId(dl.first, k)]=0;
163
 
 
164
 
 
165
 
  for (k=0; k<=2; k++) {
166
 
    if (dl.currentTrickRank[k]!=0) {
167
 
      noOfCardsPerHand[handId(dl.first, k)]=1;
168
 
      aggrRemain=0;
169
 
      for (h=0; h<=3; h++)
170
 
        aggrRemain|=(dl.remainCards[h][dl.currentTrickSuit[k]]>>2);
171
 
      if ((aggrRemain & bitMapRank[dl.currentTrickRank[k]])!=0) {
172
 
        DumpInput(-13, dl, target, solutions, mode);
173
 
        return -13;
174
 
      }
175
 
    }
176
 
  }
177
 
 
178
 
  if (target==-1)
179
 
    localVar[thrId].tricksTarget=99;
180
 
  else
181
 
    localVar[thrId].tricksTarget=target;
182
 
 
183
 
  localVar[thrId].newDeal=FALSE; localVar[thrId].newTrump=FALSE;
184
 
  localVar[thrId].diffDeal=0; localVar[thrId].aggDeal=0;
185
 
  cardCount=0;
186
 
  for (i=0; i<=3; i++) {
187
 
    for (j=0; j<=3; j++) {
188
 
      cardCount+=counttable[dl.remainCards[i][j]>>2];
189
 
      localVar[thrId].diffDeal+=((dl.remainCards[i][j]>>2)^
190
 
              (localVar[thrId].game.suit[i][j]));
191
 
      localVar[thrId].aggDeal+=(dl.remainCards[i][j]>>2);
192
 
      if (localVar[thrId].game.suit[i][j]!=dl.remainCards[i][j]>>2) {
193
 
        localVar[thrId].game.suit[i][j]=dl.remainCards[i][j]>>2;
194
 
        localVar[thrId].newDeal=TRUE;
195
 
      }
196
 
    }
197
 
  }
198
 
 
199
 
  if (localVar[thrId].newDeal) {
200
 
    if (localVar[thrId].diffDeal==0)
201
 
      localVar[thrId].similarDeal=TRUE;
202
 
    else if ((localVar[thrId].aggDeal/localVar[thrId].diffDeal)
203
 
       > SIMILARDEALLIMIT)
204
 
      localVar[thrId].similarDeal=TRUE;
205
 
    else
206
 
      localVar[thrId].similarDeal=FALSE;
207
 
  }
208
 
  else
209
 
    localVar[thrId].similarDeal=FALSE;
210
 
 
211
 
  if (dl.trump!=localVar[thrId].trump)
212
 
    localVar[thrId].newTrump=TRUE;
213
 
 
214
 
  for (i=0; i<=3; i++)
215
 
    for (j=0; j<=3; j++)
216
 
      noOfCardsPerHand[i]+=counttable[localVar[thrId].game.suit[i][j]];
217
 
 
218
 
  for (i=1; i<=3; i++) {
219
 
    if (noOfCardsPerHand[i]!=noOfCardsPerHand[0]) {
220
 
      DumpInput(-14, dl, target, solutions, mode);
221
 
      return -14;
222
 
    }
223
 
  }
224
 
 
225
 
  if (dl.currentTrickRank[2]) {
226
 
    if ((dl.currentTrickRank[2]<2)||(dl.currentTrickRank[2]>14)
227
 
      ||(dl.currentTrickSuit[2]<0)||(dl.currentTrickSuit[2]>3)) {
228
 
      DumpInput(-12, dl, target, solutions, mode);
229
 
      return -12;
230
 
    }
231
 
    localVar[thrId].handToPlay=handId(dl.first, 3);
232
 
    handRelFirst=3;
233
 
    noStartMoves=3;
234
 
    if (cardCount<=4) {
235
 
      for (k=0; k<=3; k++) {
236
 
        if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) {
237
 
          latestTrickSuit[localVar[thrId].handToPlay]=k;
238
 
          latestTrickRank[localVar[thrId].handToPlay]=
239
 
            InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]);
240
 
          break;
241
 
        }
242
 
      }
243
 
      latestTrickSuit[handId(dl.first, 2)]=dl.currentTrickSuit[2];
244
 
      latestTrickRank[handId(dl.first, 2)]=dl.currentTrickRank[2];
245
 
      latestTrickSuit[handId(dl.first, 1)]=dl.currentTrickSuit[1];
246
 
      latestTrickRank[handId(dl.first, 1)]=dl.currentTrickRank[1];
247
 
      latestTrickSuit[dl.first]=dl.currentTrickSuit[0];
248
 
      latestTrickRank[dl.first]=dl.currentTrickRank[0];
249
 
    }
250
 
  }
251
 
  else if (dl.currentTrickRank[1]) {
252
 
    if ((dl.currentTrickRank[1]<2)||(dl.currentTrickRank[1]>14)
253
 
      ||(dl.currentTrickSuit[1]<0)||(dl.currentTrickSuit[1]>3)) {
254
 
      DumpInput(-12, dl, target, solutions, mode);
255
 
      return -12;
256
 
    }
257
 
    localVar[thrId].handToPlay=handId(dl.first, 2);
258
 
    handRelFirst=2;
259
 
    noStartMoves=2;
260
 
    if (cardCount<=4) {
261
 
      for (k=0; k<=3; k++) {
262
 
        if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) {
263
 
          latestTrickSuit[localVar[thrId].handToPlay]=k;
264
 
          latestTrickRank[localVar[thrId].handToPlay]=
265
 
            InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]);
266
 
          break;
267
 
        }
268
 
      }
269
 
      for (k=0; k<=3; k++) {
270
 
        if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) {
271
 
          latestTrickSuit[handId(dl.first, 3)]=k;
272
 
          latestTrickRank[handId(dl.first, 3)]=
273
 
            InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]);
274
 
          break;
275
 
        }
276
 
      }
277
 
      latestTrickSuit[handId(dl.first, 1)]=dl.currentTrickSuit[1];
278
 
      latestTrickRank[handId(dl.first, 1)]=dl.currentTrickRank[1];
279
 
      latestTrickSuit[dl.first]=dl.currentTrickSuit[0];
280
 
      latestTrickRank[dl.first]=dl.currentTrickRank[0];
281
 
    }
282
 
  }
283
 
  else if (dl.currentTrickRank[0]) {
284
 
    if ((dl.currentTrickRank[0]<2)||(dl.currentTrickRank[0]>14)
285
 
      ||(dl.currentTrickSuit[0]<0)||(dl.currentTrickSuit[0]>3)) {
286
 
      DumpInput(-12, dl, target, solutions, mode);
287
 
      return -12;
288
 
    }
289
 
    localVar[thrId].handToPlay=handId(dl.first,1);
290
 
    handRelFirst=1;
291
 
    noStartMoves=1;
292
 
    if (cardCount<=4) {
293
 
      for (k=0; k<=3; k++) {
294
 
        if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) {
295
 
          latestTrickSuit[localVar[thrId].handToPlay]=k;
296
 
          latestTrickRank[localVar[thrId].handToPlay]=
297
 
            InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]);
298
 
          break;
299
 
        }
300
 
      }
301
 
      for (k=0; k<=3; k++) {
302
 
        if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) {
303
 
          latestTrickSuit[handId(dl.first, 3)]=k;
304
 
          latestTrickRank[handId(dl.first, 3)]=
305
 
            InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]);
306
 
          break;
307
 
        }
308
 
      }
309
 
      for (k=0; k<=3; k++) {
310
 
        if (localVar[thrId].game.suit[handId(dl.first, 2)][k]!=0) {
311
 
          latestTrickSuit[handId(dl.first, 2)]=k;
312
 
          latestTrickRank[handId(dl.first, 2)]=
313
 
            InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 2)][k]);
314
 
          break;
315
 
        }
316
 
      }
317
 
      latestTrickSuit[dl.first]=dl.currentTrickSuit[0];
318
 
      latestTrickRank[dl.first]=dl.currentTrickRank[0];
319
 
    }
320
 
  }
321
 
  else {
322
 
    localVar[thrId].handToPlay=dl.first;
323
 
    handRelFirst=0;
324
 
    noStartMoves=0;
325
 
    if (cardCount<=4) {
326
 
      for (k=0; k<=3; k++) {
327
 
        if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) {
328
 
          latestTrickSuit[localVar[thrId].handToPlay]=k;
329
 
          latestTrickRank[localVar[thrId].handToPlay]=
330
 
            InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]);
331
 
          break;
332
 
        }
333
 
      }
334
 
      for (k=0; k<=3; k++) {
335
 
        if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) {
336
 
          latestTrickSuit[handId(dl.first, 3)]=k;
337
 
          latestTrickRank[handId(dl.first, 3)]=
338
 
            InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]);
339
 
          break;
340
 
        }
341
 
      }
342
 
      for (k=0; k<=3; k++) {
343
 
        if (localVar[thrId].game.suit[handId(dl.first, 2)][k]!=0) {
344
 
          latestTrickSuit[handId(dl.first, 2)]=k;
345
 
          latestTrickRank[handId(dl.first, 2)]=
346
 
            InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 2)][k]);
347
 
          break;
348
 
        }
349
 
      }
350
 
      for (k=0; k<=3; k++) {
351
 
        if (localVar[thrId].game.suit[handId(dl.first, 1)][k]!=0) {
352
 
          latestTrickSuit[handId(dl.first, 1)]=k;
353
 
          latestTrickRank[handId(dl.first, 1)]=
354
 
            InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 1)][k]);
355
 
          break;
356
 
        }
357
 
      }
358
 
    }
359
 
  }
360
 
 
361
 
  localVar[thrId].trump=dl.trump;
362
 
  localVar[thrId].game.first=dl.first;
363
 
  first=dl.first;
364
 
  localVar[thrId].game.noOfCards=cardCount;
365
 
  if (dl.currentTrickRank[0]!=0) {
366
 
    localVar[thrId].game.leadHand=dl.first;
367
 
    localVar[thrId].game.leadSuit=dl.currentTrickSuit[0];
368
 
    localVar[thrId].game.leadRank=dl.currentTrickRank[0];
369
 
  }
370
 
  else {
371
 
    localVar[thrId].game.leadHand=0;
372
 
    localVar[thrId].game.leadSuit=0;
373
 
    localVar[thrId].game.leadRank=0;
374
 
  }
375
 
 
376
 
  for (k=0; k<=2; k++) {
377
 
    localVar[thrId].initialMoves[k].suit=255;
378
 
    localVar[thrId].initialMoves[k].rank=255;
379
 
  }
380
 
 
381
 
  for (k=0; k<noStartMoves; k++) {
382
 
    localVar[thrId].initialMoves[noStartMoves-1-k].suit=dl.currentTrickSuit[k];
383
 
    localVar[thrId].initialMoves[noStartMoves-1-k].rank=dl.currentTrickRank[k];
384
 
  }
385
 
 
386
 
  if (cardCount % 4)
387
 
    totalTricks=((cardCount-4)>>2)+2;
388
 
  else
389
 
    totalTricks=((cardCount-4)>>2)+1;
390
 
  checkRes=CheckDeal(&localVar[thrId].cd, thrId);
391
 
  if (localVar[thrId].game.noOfCards<=0) {
392
 
    DumpInput(-2, dl, target, solutions, mode);
393
 
    return -2;
394
 
  }
395
 
  if (localVar[thrId].game.noOfCards>52) {
396
 
    DumpInput(-10, dl, target, solutions, mode);
397
 
    return -10;
398
 
  }
399
 
  if (totalTricks<target) {
400
 
    DumpInput(-3, dl, target, solutions, mode);
401
 
    return -3;
402
 
  }
403
 
  if (checkRes) {
404
 
    DumpInput(-4, dl, target, solutions, mode);
405
 
    return -4;
406
 
  }
407
 
 
408
 
  if (cardCount<=4) {
409
 
    maxRank=0;
410
 
    /* Highest trump? */
411
 
    if (dl.trump!=4) {
412
 
      for (k=0; k<=3; k++) {
413
 
        if ((latestTrickSuit[k]==dl.trump)&&
414
 
          (latestTrickRank[k]>maxRank)) {
415
 
          maxRank=latestTrickRank[k];
416
 
          maxSuit=dl.trump;
417
 
          maxHand=k;
418
 
        }
419
 
      }
420
 
    }
421
 
    /* Highest card in leading suit */
422
 
    if (maxRank==0) {
423
 
      for (k=0; k<=3; k++) {
424
 
        if (k==dl.first) {
425
 
          maxSuit=latestTrickSuit[dl.first];
426
 
          maxHand=dl.first;
427
 
          maxRank=latestTrickRank[dl.first];
428
 
          break;
429
 
        }
430
 
      }
431
 
      for (k=0; k<=3; k++) {
432
 
        if ((k!=dl.first)&&(latestTrickSuit[k]==maxSuit)&&
433
 
          (latestTrickRank[k]>maxRank)) {
434
 
          maxHand=k;
435
 
          maxRank=latestTrickRank[k];
436
 
        }
437
 
      }
438
 
    }
439
 
    futp->nodes=0;
440
 
    #ifdef BENCH
441
 
    futp->totalNodes=0;
442
 
    #endif
443
 
    futp->cards=1;
444
 
    futp->suit[0]=latestTrickSuit[localVar[thrId].handToPlay];
445
 
    futp->rank[0]=latestTrickRank[localVar[thrId].handToPlay];
446
 
    futp->equals[0]=0;
447
 
    if ((target==0)&&(solutions<3))
448
 
      futp->score[0]=0;
449
 
    else if ((localVar[thrId].handToPlay==maxHand)||
450
 
        (partner[localVar[thrId].handToPlay]==maxHand))
451
 
      futp->score[0]=1;
452
 
    else
453
 
      futp->score[0]=0;
454
 
 
455
 
        /*_CrtDumpMemoryLeaks();*/  /* MEMORY LEAK? */
456
 
    return 1;
457
 
  }
458
 
 
459
 
  if ((mode!=2)&&
460
 
    (((localVar[thrId].newDeal)&&(!localVar[thrId].similarDeal))
461
 
      || localVar[thrId].newTrump  ||
462
 
          (localVar[thrId].winSetSize > SIMILARMAXWINNODES))) {
463
 
 
464
 
    Wipe(thrId);
465
 
        localVar[thrId].winSetSizeLimit=WINIT;
466
 
    localVar[thrId].nodeSetSizeLimit=NINIT;
467
 
    localVar[thrId].lenSetSizeLimit=LINIT;
468
 
    localVar[thrId].allocmem=(WINIT+1)*sizeof(struct winCardType);
469
 
    localVar[thrId].allocmem+=(NINIT+1)*sizeof(struct nodeCardsType);
470
 
    localVar[thrId].allocmem+=(LINIT+1)*sizeof(struct posSearchType);
471
 
    localVar[thrId].winCards=localVar[thrId].pw[0];
472
 
    localVar[thrId].nodeCards=localVar[thrId].pn[0];
473
 
    localVar[thrId].posSearch=localVar[thrId].pl[0];
474
 
    localVar[thrId].wcount=0; localVar[thrId].ncount=0; localVar[thrId].lcount=0;
475
 
    InitGame(0, FALSE, first, handRelFirst, thrId);
476
 
  }
477
 
  else {
478
 
    InitGame(0, TRUE, first, handRelFirst, thrId);
479
 
        /*localVar[thrId].fp2=fopen("dyn.txt", "a");
480
 
        fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n",
481
 
          wcount, ncount, lcount);
482
 
    fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n",
483
 
          winSetSize, nodeSetSize, lenSetSize);
484
 
    fclose(localVar[thrId].fp2);*/
485
 
  }
486
 
 
487
 
  localVar[thrId].nodes=0; localVar[thrId].trickNodes=0;
488
 
  localVar[thrId].iniDepth=cardCount-4;
489
 
  hiwinSetSize=0;
490
 
  hinodeSetSize=0;
491
 
 
492
 
  if (mode==0) {
493
 
    MoveGen(&localVar[thrId].lookAheadPos, localVar[thrId].iniDepth, localVar[thrId].trump,
494
 
                &localVar[thrId].movePly[localVar[thrId].iniDepth], thrId);
495
 
    if (localVar[thrId].movePly[localVar[thrId].iniDepth].last==0) {
496
 
        futp->nodes=0;
497
 
    #ifdef BENCH
498
 
        futp->totalNodes=0;
499
 
    #endif
500
 
        futp->cards=1;
501
 
        futp->suit[0]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].suit;
502
 
        futp->rank[0]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].rank;
503
 
        futp->equals[0]=
504
 
          localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].sequence<<2;
505
 
        futp->score[0]=-2;
506
 
 
507
 
        /*_CrtDumpMemoryLeaks();*/  /* MEMORY LEAK? */
508
 
        return 1;
509
 
    }
510
 
  }
511
 
  if ((target==0)&&(solutions<3)) {
512
 
    MoveGen(&localVar[thrId].lookAheadPos, localVar[thrId].iniDepth, localVar[thrId].trump,
513
 
                &localVar[thrId].movePly[localVar[thrId].iniDepth], thrId);
514
 
    futp->nodes=0;
515
 
    #ifdef BENCH
516
 
    futp->totalNodes=0;
517
 
    #endif
518
 
    for (k=0; k<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; k++) {
519
 
        futp->suit[k]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].suit;
520
 
        futp->rank[k]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].rank;
521
 
        futp->equals[k]=
522
 
          localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].sequence<<2;
523
 
        futp->score[k]=0;
524
 
    }
525
 
    if (solutions==1)
526
 
        futp->cards=1;
527
 
    else
528
 
        futp->cards=localVar[thrId].movePly[localVar[thrId].iniDepth].last+1;
529
 
 
530
 
        /*_CrtDumpMemoryLeaks(); */ /* MEMORY LEAK? */
531
 
    return 1;
532
 
  }
533
 
 
534
 
  if ((target!=-1)&&(solutions!=3)) {
535
 
    localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos,
536
 
                localVar[thrId].tricksTarget, localVar[thrId].iniDepth, thrId);
537
 
 
538
 
    temp=localVar[thrId].movePly[localVar[thrId].iniDepth];
539
 
    last=localVar[thrId].movePly[localVar[thrId].iniDepth].last;
540
 
    noMoves=last+1;
541
 
    hiwinSetSize=localVar[thrId].winSetSize;
542
 
    hinodeSetSize=localVar[thrId].nodeSetSize;
543
 
    hilenSetSize=localVar[thrId].lenSetSize;
544
 
    if (localVar[thrId].nodeSetSize>MaxnodeSetSize)
545
 
      MaxnodeSetSize=localVar[thrId].nodeSetSize;
546
 
    if (localVar[thrId].winSetSize>MaxwinSetSize)
547
 
      MaxwinSetSize=localVar[thrId].winSetSize;
548
 
    if (localVar[thrId].lenSetSize>MaxlenSetSize)
549
 
      MaxlenSetSize=localVar[thrId].lenSetSize;
550
 
    if (localVar[thrId].val==1)
551
 
      localVar[thrId].payOff=localVar[thrId].tricksTarget;
552
 
    else
553
 
      localVar[thrId].payOff=0;
554
 
    futp->cards=1;
555
 
    ind=2;
556
 
 
557
 
    if (localVar[thrId].payOff<=0) {
558
 
      futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit;
559
 
      futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank;
560
 
        futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2;
561
 
      if (localVar[thrId].tricksTarget>1)
562
 
        futp->score[0]=-1;
563
 
      else
564
 
        futp->score[0]=0;
565
 
    }
566
 
    else {
567
 
      futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
568
 
      futp->rank[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
569
 
        futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2;
570
 
      futp->score[0]=localVar[thrId].payOff;
571
 
    }
572
 
  }
573
 
  else {
574
 
    g=localVar[thrId].estTricks[localVar[thrId].handToPlay];
575
 
    upperbound=13;
576
 
    lowerbound=0;
577
 
    do {
578
 
      if (g==lowerbound)
579
 
        tricks=g+1;
580
 
      else
581
 
        tricks=g;
582
 
          assert((localVar[thrId].lookAheadPos.handRelFirst>=0)&&
583
 
                (localVar[thrId].lookAheadPos.handRelFirst<=3));
584
 
      localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, tricks,
585
 
                  localVar[thrId].iniDepth, thrId);
586
 
 
587
 
      if (localVar[thrId].val==TRUE)
588
 
        mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4];
589
 
      hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize);
590
 
      hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize);
591
 
        hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize);
592
 
      if (localVar[thrId].nodeSetSize>MaxnodeSetSize)
593
 
        MaxnodeSetSize=localVar[thrId].nodeSetSize;
594
 
      if (localVar[thrId].winSetSize>MaxwinSetSize)
595
 
        MaxwinSetSize=localVar[thrId].winSetSize;
596
 
        if (localVar[thrId].lenSetSize>MaxlenSetSize)
597
 
        MaxlenSetSize=localVar[thrId].lenSetSize;
598
 
      if (localVar[thrId].val==FALSE) {
599
 
        upperbound=tricks-1;
600
 
        g=upperbound;
601
 
      }
602
 
      else {
603
 
        lowerbound=tricks;
604
 
        g=lowerbound;
605
 
      }
606
 
      InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4,
607
 
        localVar[thrId].initialMoves, first, TRUE, thrId);
608
 
    }
609
 
    while (lowerbound<upperbound);
610
 
    localVar[thrId].payOff=g;
611
 
    temp=localVar[thrId].movePly[localVar[thrId].iniDepth];
612
 
    last=localVar[thrId].movePly[localVar[thrId].iniDepth].last;
613
 
    noMoves=last+1;
614
 
    ind=2;
615
 
    localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]=mv;
616
 
    futp->cards=1;
617
 
    if (localVar[thrId].payOff<=0) {
618
 
      futp->score[0]=0;
619
 
      futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit;
620
 
      futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank;
621
 
      futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2;
622
 
    }
623
 
    else {
624
 
      futp->score[0]=localVar[thrId].payOff;
625
 
      futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
626
 
      futp->rank[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
627
 
      futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2;
628
 
    }
629
 
    localVar[thrId].tricksTarget=localVar[thrId].payOff;
630
 
  }
631
 
 
632
 
  if ((solutions==2)&&(localVar[thrId].payOff>0)) {
633
 
    forb=1;
634
 
    ind=forb;
635
 
    while ((localVar[thrId].payOff==localVar[thrId].tricksTarget)&&(ind<(temp.last+1))) {
636
 
      localVar[thrId].forbiddenMoves[forb].suit=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
637
 
      localVar[thrId].forbiddenMoves[forb].rank=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
638
 
      forb++; ind++;
639
 
      /* All moves before bestMove in the move list shall be
640
 
      moved to the forbidden moves list, since none of them reached
641
 
      the target */
642
 
      mcurr=localVar[thrId].movePly[localVar[thrId].iniDepth].current;
643
 
      for (k=0; k<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; k++)
644
 
        if ((localVar[thrId].bestMove[localVar[thrId].iniDepth].suit==
645
 
                        localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].suit)
646
 
          &&(localVar[thrId].bestMove[localVar[thrId].iniDepth].rank==
647
 
                    localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].rank))
648
 
          break;
649
 
      for (i=0; i<k; i++) {  /* All moves until best move */
650
 
        flag=FALSE;
651
 
        for (j=0; j<forb; j++) {
652
 
          if ((localVar[thrId].movePly[localVar[thrId].iniDepth].move[i].suit==localVar[thrId].forbiddenMoves[j].suit)
653
 
            &&(localVar[thrId].movePly[localVar[thrId].iniDepth].move[i].rank==localVar[thrId].forbiddenMoves[j].rank)) {
654
 
            /* If the move is already in the forbidden list */
655
 
            flag=TRUE;
656
 
            break;
657
 
          }
658
 
        }
659
 
        if (!flag) {
660
 
          localVar[thrId].forbiddenMoves[forb]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[i];
661
 
          forb++;
662
 
        }
663
 
      }
664
 
      InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4,
665
 
          localVar[thrId].initialMoves, first, TRUE, thrId);
666
 
      localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, localVar[thrId].tricksTarget,
667
 
                  localVar[thrId].iniDepth, thrId);
668
 
 
669
 
      hiwinSetSize=localVar[thrId].winSetSize;
670
 
      hinodeSetSize=localVar[thrId].nodeSetSize;
671
 
      hilenSetSize=localVar[thrId].lenSetSize;
672
 
      if (localVar[thrId].nodeSetSize>MaxnodeSetSize)
673
 
        MaxnodeSetSize=localVar[thrId].nodeSetSize;
674
 
      if (localVar[thrId].winSetSize>MaxwinSetSize)
675
 
        MaxwinSetSize=localVar[thrId].winSetSize;
676
 
      if (localVar[thrId].lenSetSize>MaxlenSetSize)
677
 
        MaxlenSetSize=localVar[thrId].lenSetSize;
678
 
      if (localVar[thrId].val==TRUE) {
679
 
        localVar[thrId].payOff=localVar[thrId].tricksTarget;
680
 
        futp->cards=ind;
681
 
        futp->suit[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
682
 
        futp->rank[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
683
 
        futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2;
684
 
        futp->score[ind-1]=localVar[thrId].payOff;
685
 
      }
686
 
      else
687
 
        localVar[thrId].payOff=0;
688
 
    }
689
 
  }
690
 
  else if ((solutions==2)&&(localVar[thrId].payOff==0)&&
691
 
        ((target==-1)||(localVar[thrId].tricksTarget==1))) {
692
 
    futp->cards=noMoves;
693
 
    /* Find the cards that were in the initial move list
694
 
    but have not been listed in the current result */
695
 
    n=0;
696
 
    for (i=0; i<noMoves; i++) {
697
 
      found=FALSE;
698
 
      if ((temp.move[i].suit==futp->suit[0])&&
699
 
        (temp.move[i].rank==futp->rank[0])) {
700
 
        found=TRUE;
701
 
      }
702
 
      if (!found) {
703
 
        futp->suit[1+n]=temp.move[i].suit;
704
 
        futp->rank[1+n]=temp.move[i].rank;
705
 
          futp->equals[1+n]=(temp.move[i].sequence)<<2;
706
 
        futp->score[1+n]=0;
707
 
        n++;
708
 
      }
709
 
    }
710
 
  }
711
 
 
712
 
  if ((solutions==3)&&(localVar[thrId].payOff>0)) {
713
 
    forb=1;
714
 
    ind=forb;
715
 
    for (i=0; i<last; i++) {
716
 
      localVar[thrId].forbiddenMoves[forb].suit=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
717
 
      localVar[thrId].forbiddenMoves[forb].rank=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
718
 
      forb++; ind++;
719
 
 
720
 
      g=localVar[thrId].payOff;
721
 
      upperbound=localVar[thrId].payOff;
722
 
      lowerbound=0;
723
 
 
724
 
      InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4,
725
 
          localVar[thrId].initialMoves, first, TRUE, thrId);
726
 
      do {
727
 
        if (g==lowerbound)
728
 
          tricks=g+1;
729
 
        else
730
 
          tricks=g;
731
 
        assert((localVar[thrId].lookAheadPos.handRelFirst>=0)&&
732
 
                  (localVar[thrId].lookAheadPos.handRelFirst<=3));
733
 
        localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, tricks,
734
 
                        localVar[thrId].iniDepth, thrId);
735
 
 
736
 
        if (localVar[thrId].val==TRUE)
737
 
          mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4];
738
 
        hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize);
739
 
        hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize);
740
 
        hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize);
741
 
        if (localVar[thrId].nodeSetSize>MaxnodeSetSize)
742
 
          MaxnodeSetSize=localVar[thrId].nodeSetSize;
743
 
        if (localVar[thrId].winSetSize>MaxwinSetSize)
744
 
          MaxwinSetSize=localVar[thrId].winSetSize;
745
 
        if (localVar[thrId].lenSetSize>MaxlenSetSize)
746
 
          MaxlenSetSize=localVar[thrId].lenSetSize;
747
 
        if (localVar[thrId].val==FALSE) {
748
 
          upperbound=tricks-1;
749
 
          g=upperbound;
750
 
        }
751
 
        else {
752
 
          lowerbound=tricks;
753
 
          g=lowerbound;
754
 
        }
755
 
 
756
 
        InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4,
757
 
          localVar[thrId].initialMoves, first, TRUE, thrId);
758
 
      }
759
 
      while (lowerbound<upperbound);
760
 
      localVar[thrId].payOff=g;
761
 
      if (localVar[thrId].payOff==0) {
762
 
        last=localVar[thrId].movePly[localVar[thrId].iniDepth].last;
763
 
        futp->cards=temp.last+1;
764
 
        for (j=0; j<=last; j++) {
765
 
          futp->suit[ind-1+j]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].suit;
766
 
          futp->rank[ind-1+j]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].rank;
767
 
            futp->equals[ind-1+j]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].sequence)<<2;
768
 
          futp->score[ind-1+j]=localVar[thrId].payOff;
769
 
        }
770
 
        break;
771
 
      }
772
 
      else {
773
 
        localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]=mv;
774
 
 
775
 
        futp->cards=ind;
776
 
        futp->suit[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
777
 
        futp->rank[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
778
 
          futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2;
779
 
        futp->score[ind-1]=localVar[thrId].payOff;
780
 
      }
781
 
    }
782
 
  }
783
 
  else if ((solutions==3)&&(localVar[thrId].payOff==0)) {
784
 
    futp->cards=noMoves;
785
 
    /* Find the cards that were in the initial move list
786
 
    but have not been listed in the current result */
787
 
    n=0;
788
 
    for (i=0; i<noMoves; i++) {
789
 
      found=FALSE;
790
 
      if ((temp.move[i].suit==futp->suit[0])&&
791
 
        (temp.move[i].rank==futp->rank[0])) {
792
 
          found=TRUE;
793
 
      }
794
 
      if (!found) {
795
 
        futp->suit[1+n]=temp.move[i].suit;
796
 
        futp->rank[1+n]=temp.move[i].rank;
797
 
          futp->equals[1+n]=(temp.move[i].sequence)<<2;
798
 
        futp->score[1+n]=0;
799
 
        n++;
800
 
      }
801
 
    }
802
 
  }
803
 
 
804
 
  for (k=0; k<=13; k++) {
805
 
    localVar[thrId].forbiddenMoves[k].suit=0;
806
 
    localVar[thrId].forbiddenMoves[k].rank=0;
807
 
  }
808
 
 
809
 
  futp->nodes=localVar[thrId].trickNodes;
810
 
  #ifdef BENCH
811
 
  futp->totalNodes=localVar[thrId].nodes;
812
 
  #endif
813
 
  /*if ((wcount>0)||(ncount>0)||(lcount>0)) {
814
 
    localVar[thrId].fp2=fopen("dyn.txt", "a");
815
 
        fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n",
816
 
          wcount, ncount, lcount);
817
 
    fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n",
818
 
          winSetSize, nodeSetSize, lenSetSize);
819
 
        fprintf(localVar[thrId].fp2, "\n");
820
 
    fclose(localVar[thrId].fp2);
821
 
  }*/
822
 
 
823
 
  /*_CrtDumpMemoryLeaks();*/  /* MEMORY LEAK? */
824
 
  return 1;
825
 
}
826
 
 
827
 
 
828
 
int _initialized=0;
829
 
 
830
 
void InitStart(int gb_ram, int ncores) {
831
 
  int k, r, i, j, m;
832
 
  unsigned short int res;
833
 
  unsigned long long pcmem;     /* kbytes */
834
 
 
835
 
  if (_initialized)
836
 
    return;
837
 
  _initialized = 1;
838
 
 
839
 
  ttCollect=FALSE;
840
 
  suppressTTlog=FALSE;
841
 
  lastTTstore=0;
842
 
  ttStore = (struct ttStoreType *)calloc(SEARCHSIZE, sizeof(struct ttStoreType));
843
 
  if (ttStore==NULL)
844
 
    exit(1);
845
 
 
846
 
  if (gb_ram==0) {              /* Autoconfig */
847
 
 
848
 
  #ifdef _WIN32
849
 
 
850
 
    SYSTEM_INFO temp;
851
 
 
852
 
    MEMORYSTATUSEX statex;
853
 
        statex.dwLength = sizeof (statex);
854
 
 
855
 
    GlobalMemoryStatusEx (&statex);     /* Using GlobalMemoryStatusEx instead of GlobalMemoryStatus
856
 
                                        was suggested by Lorne Anderson. */
857
 
 
858
 
    pcmem=(unsigned long long)statex.ullTotalPhys/1024;
859
 
 
860
 
    if (pcmem < 1500000)
861
 
      noOfThreads=Min(MAXNOOFTHREADS, 2);
862
 
    else if (pcmem < 2500000)
863
 
      noOfThreads=Min(MAXNOOFTHREADS, 4);
864
 
    else
865
 
      noOfThreads=MAXNOOFTHREADS;
866
 
 
867
 
    GetSystemInfo(&temp);
868
 
    noOfCores=Min(noOfThreads, (int)temp.dwNumberOfProcessors);
869
 
 
870
 
  #endif
871
 
  #ifdef __linux__   /* The code for linux was suggested by Antony Lee. */
872
 
    FILE* fifo = popen("free -k | tail -n+3 | head -n1 | awk '{print $NF}'", "r");
873
 
    fscanf(fifo, "%ld", &pcmem);
874
 
    fclose(fifo);
875
 
  #endif
876
 
 
877
 
  }
878
 
  else {
879
 
    if (gb_ram < 2)
880
 
      noOfThreads=Min(MAXNOOFTHREADS, 2);
881
 
    else if (gb_ram < 3)
882
 
      noOfThreads=Min(MAXNOOFTHREADS, 4);
883
 
    else
884
 
      noOfThreads=Min(MAXNOOFTHREADS, 8);
885
 
 
886
 
    noOfCores=Min(noOfThreads, ncores);
887
 
 
888
 
    pcmem=(unsigned long long)(1000000 * gb_ram);
889
 
  }
890
 
 
891
 
  /*printf("noOfThreads: %d   noOfCores: %d\n", noOfThreads, noOfCores);*/
892
 
 
893
 
  for (k=0; k<noOfThreads; k++) {
894
 
    localVar[k].trump=-1;
895
 
    localVar[k].nodeSetSizeLimit=0;
896
 
    localVar[k].winSetSizeLimit=0;
897
 
    localVar[k].lenSetSizeLimit=0;
898
 
    localVar[k].clearTTflag=FALSE;
899
 
    localVar[k].windex=-1;
900
 
 
901
 
    localVar[k].nodeSetSize=0; /* Index with range 0 to nodeSetSizeLimit */
902
 
    localVar[k].winSetSize=0;  /* Index with range 0 to winSetSizeLimit */
903
 
    localVar[k].lenSetSize=0;  /* Index with range 0 to lenSetSizeLimit */
904
 
 
905
 
    localVar[k].nodeSetSizeLimit=NINIT;
906
 
    localVar[k].winSetSizeLimit=WINIT;
907
 
    localVar[k].lenSetSizeLimit=LINIT;
908
 
 
909
 
    if ((gb_ram!=0)&&(ncores!=0))
910
 
      localVar[k].maxmem=gb_ram * ((8000001*sizeof(struct nodeCardsType)+
911
 
                   25000001*sizeof(struct winCardType)+
912
 
                   400001*sizeof(struct posSearchType))/noOfThreads);
913
 
    else {
914
 
      localVar[k].maxmem = (unsigned long long)(pcmem-32768) * (700/noOfThreads);
915
 
          /* Linear calculation of maximum memory, formula by Michiel de Bondt */
916
 
 
917
 
      if (localVar[k].maxmem < 10485760) exit (1);
918
 
    }
919
 
 
920
 
    /*printf("thread no: %d  maxmem: %ld\n", k, localVar[k].maxmem);*/
921
 
  }
922
 
 
923
 
  bitMapRank[15]=0x2000;
924
 
  bitMapRank[14]=0x1000;
925
 
  bitMapRank[13]=0x0800;
926
 
  bitMapRank[12]=0x0400;
927
 
  bitMapRank[11]=0x0200;
928
 
  bitMapRank[10]=0x0100;
929
 
  bitMapRank[9]=0x0080;
930
 
  bitMapRank[8]=0x0040;
931
 
  bitMapRank[7]=0x0020;
932
 
  bitMapRank[6]=0x0010;
933
 
  bitMapRank[5]=0x0008;
934
 
  bitMapRank[4]=0x0004;
935
 
  bitMapRank[3]=0x0002;
936
 
  bitMapRank[2]=0x0001;
937
 
  bitMapRank[1]=0;
938
 
  bitMapRank[0]=0;
939
 
 
940
 
  lho[0]=1; lho[1]=2; lho[2]=3; lho[3]=0;
941
 
  rho[0]=3; rho[1]=0; rho[2]=1; rho[3]=2;
942
 
  partner[0]=2; partner[1]=3; partner[2]=0; partner[3]=1;
943
 
 
944
 
  cardRank[2]='2'; cardRank[3]='3'; cardRank[4]='4'; cardRank[5]='5';
945
 
  cardRank[6]='6'; cardRank[7]='7'; cardRank[8]='8'; cardRank[9]='9';
946
 
  cardRank[10]='T'; cardRank[11]='J'; cardRank[12]='Q'; cardRank[13]='K';
947
 
  cardRank[14]='A';
948
 
 
949
 
  cardSuit[0]='S'; cardSuit[1]='H'; cardSuit[2]='D'; cardSuit[3]='C';
950
 
  cardSuit[4]='N';
951
 
 
952
 
  cardHand[0]='N'; cardHand[1]='E'; cardHand[2]='S'; cardHand[3]='W';
953
 
 
954
 
  max_low[0][0]=0; max_low[1][0]=0; max_low[2][0]=0;
955
 
  max_low[0][1]=0; max_low[1][1]=0; max_low[2][1]=0;
956
 
  max_low[0][2]=1; max_low[1][2]=1; max_low[2][2]=1;
957
 
  max_low[0][3]=0; max_low[1][3]=2; max_low[2][3]=2;
958
 
  max_low[0][4]=1; max_low[1][4]=0; max_low[2][4]=3;
959
 
  max_low[0][5]=2; max_low[1][5]=1; max_low[2][5]=0;
960
 
  max_low[0][6]=0; max_low[1][6]=0; max_low[2][6]=0;
961
 
  max_low[0][7]=0; max_low[1][7]=0; max_low[2][7]=0;
962
 
 
963
 
  for (k=0; k<noOfThreads; k++) {
964
 
    localVar[k].summem=(WINIT+1)*sizeof(struct winCardType)+
965
 
             (NINIT+1)*sizeof(struct nodeCardsType)+
966
 
                 (LINIT+1)*sizeof(struct posSearchType);
967
 
    localVar[k].wmem=(WSIZE+1)*sizeof(struct winCardType);
968
 
    localVar[k].nmem=(NSIZE+1)*sizeof(struct nodeCardsType);
969
 
    localVar[k].lmem=(LSIZE+1)*sizeof(struct posSearchType);
970
 
        localVar[k].maxIndex=(int)(
971
 
       (localVar[k].maxmem-localVar[k].summem)/((WSIZE+1) * sizeof(struct winCardType)));
972
 
 
973
 
    localVar[k].pw = (struct winCardType **)calloc(localVar[k].maxIndex+1, sizeof(struct winCardType *));
974
 
    if (localVar[k].pw==NULL)
975
 
      exit(1);
976
 
    localVar[k].pn = (struct nodeCardsType **)calloc(localVar[k].maxIndex+1, sizeof(struct nodeCardsType *));
977
 
    if (localVar[k].pn==NULL)
978
 
      exit(1);
979
 
    localVar[k].pl = (struct posSearchType **)calloc(localVar[k].maxIndex+1, sizeof(struct posSearchType *));
980
 
    if (localVar[k].pl==NULL)
981
 
      exit(1);
982
 
    for (i=0; i<=localVar[k].maxIndex; i++) {
983
 
      if (localVar[k].pw[i])
984
 
        free(localVar[k].pw[i]);
985
 
      localVar[k].pw[i]=NULL;
986
 
    }
987
 
    for (i=0; i<=localVar[k].maxIndex; i++) {
988
 
      if (localVar[k].pn[i])
989
 
        free(localVar[k].pn[i]);
990
 
      localVar[k].pn[i]=NULL;
991
 
    }
992
 
    for (i=0; i<=localVar[k].maxIndex; i++) {
993
 
      if (localVar[k].pl[i])
994
 
        free(localVar[k].pl[i]);
995
 
      localVar[k].pl[i]=NULL;
996
 
    }
997
 
 
998
 
    localVar[k].pw[0] = (struct winCardType *)calloc(localVar[k].winSetSizeLimit+1, sizeof(struct winCardType));
999
 
    if (localVar[k].pw[0]==NULL)
1000
 
      exit(1);
1001
 
    localVar[k].allocmem=(localVar[k].winSetSizeLimit+1)*sizeof(struct winCardType);
1002
 
    localVar[k].winCards=localVar[k].pw[0];
1003
 
    localVar[k].pn[0] = (struct nodeCardsType *)calloc(localVar[k].nodeSetSizeLimit+1, sizeof(struct nodeCardsType));
1004
 
    if (localVar[k].pn[0]==NULL)
1005
 
      exit(1);
1006
 
    localVar[k].allocmem+=(localVar[k].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType);
1007
 
    localVar[k].nodeCards=localVar[k].pn[0];
1008
 
    localVar[k].pl[0] =
1009
 
          (struct posSearchType *)calloc(localVar[k].lenSetSizeLimit+1, sizeof(struct posSearchType));
1010
 
    if (localVar[k].pl[0]==NULL)
1011
 
     exit(1);
1012
 
    localVar[k].allocmem+=(localVar[k].lenSetSizeLimit+1)*sizeof(struct posSearchType);
1013
 
    localVar[k].posSearch=localVar[k].pl[0];
1014
 
    localVar[k].wcount=0; localVar[k].ncount=0; localVar[k].lcount=0;
1015
 
 
1016
 
    localVar[k].rel = (struct relRanksType *)calloc(8192, sizeof(struct relRanksType));
1017
 
    if (localVar[k].rel==NULL)
1018
 
      exit(1);
1019
 
 
1020
 
    localVar[k].adaptWins = (struct adaptWinRanksType *)calloc(8192,
1021
 
          sizeof(struct adaptWinRanksType));
1022
 
    if (localVar[k].adaptWins==NULL)
1023
 
      exit(1);
1024
 
  }
1025
 
 
1026
 
  highestRank = (int *)calloc(8192, sizeof(int));
1027
 
  if (highestRank==NULL)
1028
 
    exit(1);
1029
 
 
1030
 
  highestRank[0]=0;
1031
 
  for (k=1; k<8192; k++) {
1032
 
    for (r=14; r>=2; r--) {
1033
 
      if ((k & bitMapRank[r])!=0) {
1034
 
        highestRank[k]=r;
1035
 
          break;
1036
 
      }
1037
 
    }
1038
 
  }
1039
 
 
1040
 
  /* The use of the counttable to give the number of bits set to
1041
 
  one in an integer follows an implementation by Thomas Andrews. */
1042
 
 
1043
 
  counttable = (int *)calloc(8192, sizeof(int));
1044
 
  if (counttable==NULL)
1045
 
    exit(1);
1046
 
 
1047
 
  for (i=0; i<8192; i++) {
1048
 
    counttable[i]=0;
1049
 
    for (j=0; j<13; j++) {
1050
 
      if (i & (1<<j)) {counttable[i]++;}
1051
 
    }
1052
 
  }
1053
 
 
1054
 
 
1055
 
  for (i=0; i<8192; i++)
1056
 
    for (j=0; j<14; j++) {
1057
 
      res=0;
1058
 
      if (j==0) {
1059
 
        for (m=0; m<noOfThreads; m++)
1060
 
          localVar[m].adaptWins[i].winRanks[j]=0;
1061
 
      }
1062
 
      else {
1063
 
        k=1;
1064
 
        for (r=14; r>=2; r--) {
1065
 
          if ((i & bitMapRank[r])!=0) {
1066
 
            if (k <= j) {
1067
 
              res|=bitMapRank[r];
1068
 
              k++;
1069
 
            }
1070
 
            else
1071
 
              break;
1072
 
          }
1073
 
        }
1074
 
        for (m=0; m<noOfThreads; m++)
1075
 
          localVar[m].adaptWins[i].winRanks[j]=res;
1076
 
      }
1077
 
    }
1078
 
 
1079
 
  /*localVar[thrId].fp2=fopen("dyn.txt", "w");
1080
 
  fclose(localVar[thrId].fp2);*/
1081
 
  /*localVar[thrId].fp2=fopen("dyn.txt", "a");
1082
 
  fprintf(localVar[thrId].fp2, "maxIndex=%ld\n", maxIndex);
1083
 
  fclose(localVar[thrId].fp2);*/
1084
 
 
1085
 
  return;
1086
 
}
1087
 
 
1088
 
 
1089
 
void InitGame(int gameNo, int moveTreeFlag, int first, int handRelFirst, int thrId) {
1090
 
 
1091
 
  int k, s, h, m, ord, r;
1092
 
  unsigned int topBitRank=1;
1093
 
  unsigned short int ind;
1094
 
 
1095
 
  #ifdef STAT
1096
 
    localVar[thrId].fp2=fopen("stat.txt","w");
1097
 
  #endif
1098
 
 
1099
 
  #ifdef TTDEBUG
1100
 
  if (!suppressTTlog) {
1101
 
    localVar[thrId].fp7=fopen("storett.txt","w");
1102
 
    localVar[thrId].fp11=fopen("rectt.txt", "w");
1103
 
    fclose(localVar[thrId].fp11);
1104
 
    ttCollect=TRUE;
1105
 
  }
1106
 
  #endif
1107
 
 
1108
 
 
1109
 
  if (localVar[thrId].newDeal) {
1110
 
 
1111
 
    /* Initialization of the rel structure is implemented
1112
 
       according to a solution given by Thomas Andrews */
1113
 
 
1114
 
    for (k=0; k<=3; k++)
1115
 
      for (m=0; m<=3; m++)
1116
 
        localVar[thrId].iniPosition.rankInSuit[k][m]=localVar[thrId].game.suit[k][m];
1117
 
 
1118
 
    for (s=0; s<4; s++) {
1119
 
      localVar[thrId].rel[0].aggrRanks[s]=0;
1120
 
      localVar[thrId].rel[0].winMask[s]=0;
1121
 
      for (ord=1; ord<=13; ord++) {
1122
 
        localVar[thrId].rel[0].absRank[ord][s].hand=-1;
1123
 
        localVar[thrId].rel[0].absRank[ord][s].rank=0;
1124
 
      }
1125
 
      for (r=2; r<=14; r++)
1126
 
        localVar[thrId].rel[0].relRank[r][s]=0;
1127
 
    }
1128
 
 
1129
 
    for (ind=1; ind<8192; ind++) {
1130
 
      if (ind>=(topBitRank+topBitRank)) {
1131
 
       /* Next top bit */
1132
 
        topBitRank <<=1;
1133
 
      }
1134
 
 
1135
 
      localVar[thrId].rel[ind]=localVar[thrId].rel[ind ^ topBitRank];
1136
 
 
1137
 
      for (s=0; s<4; s++) {
1138
 
        ord=0;
1139
 
        for (r=14; r>=2; r--) {
1140
 
          if ((ind & bitMapRank[r])!=0) {
1141
 
            ord++;
1142
 
            localVar[thrId].rel[ind].relRank[r][s]=ord;
1143
 
            for (h=0; h<4; h++) {
1144
 
              if ((localVar[thrId].game.suit[h][s] & bitMapRank[r])!=0) {
1145
 
                localVar[thrId].rel[ind].absRank[ord][s].hand=h;
1146
 
                localVar[thrId].rel[ind].absRank[ord][s].rank=r;
1147
 
                break;
1148
 
              }
1149
 
            }
1150
 
          }
1151
 
        }
1152
 
        for (k=ord+1; k<=13; k++) {
1153
 
          localVar[thrId].rel[ind].absRank[k][s].hand=-1;
1154
 
          localVar[thrId].rel[ind].absRank[k][s].rank=0;
1155
 
        }
1156
 
        for (h=0; h<4; h++) {
1157
 
          if (localVar[thrId].game.suit[h][s] & topBitRank) {
1158
 
            localVar[thrId].rel[ind].aggrRanks[s]=
1159
 
                  (localVar[thrId].rel[ind].aggrRanks[s]>>2)|(h<<24);
1160
 
            localVar[thrId].rel[ind].winMask[s]=
1161
 
                  (localVar[thrId].rel[ind].winMask[s]>>2)|(3<<24);
1162
 
            break;
1163
 
          }
1164
 
        }
1165
 
      }
1166
 
    }
1167
 
  }
1168
 
 
1169
 
  localVar[thrId].iniPosition.first[localVar[thrId].game.noOfCards-4]=first;
1170
 
  localVar[thrId].iniPosition.handRelFirst=handRelFirst;
1171
 
  localVar[thrId].lookAheadPos=localVar[thrId].iniPosition;
1172
 
 
1173
 
  localVar[thrId].estTricks[1]=6;
1174
 
  localVar[thrId].estTricks[3]=6;
1175
 
  localVar[thrId].estTricks[0]=7;
1176
 
  localVar[thrId].estTricks[2]=7;
1177
 
 
1178
 
  #ifdef STAT
1179
 
  fprintf(localVar[thrId].fp2, "Estimated tricks for hand to play:\n");
1180
 
  fprintf(localVar[thrId].fp2, "hand=%d  est tricks=%d\n",
1181
 
          localVar[thrId].handToPlay, localVar[thrId].estTricks[localVar[thrId].handToPlay]);
1182
 
  #endif
1183
 
 
1184
 
  InitSearch(&localVar[thrId].lookAheadPos, localVar[thrId].game.noOfCards-4,
1185
 
        localVar[thrId].initialMoves, first, moveTreeFlag, thrId);
1186
 
  return;
1187
 
}
1188
 
 
1189
 
 
1190
 
void InitSearch(struct pos * posPoint, int depth, struct moveType startMoves[],
1191
 
        int first, int mtd, int thrId)  {
1192
 
 
1193
 
  int s, d, h, handRelFirst, maxAgg, maxHand=0;
1194
 
  int k, noOfStartMoves;       /* Number of start moves in the 1st trick */
1195
 
  int hand[3], suit[3], rank[3];
1196
 
  struct moveType move;
1197
 
  unsigned short int startMovesBitMap[4][4]; /* Indices are hand and suit */
1198
 
  unsigned short int aggHand[4][4];
1199
 
 
1200
 
  for (h=0; h<=3; h++)
1201
 
    for (s=0; s<=3; s++)
1202
 
      startMovesBitMap[h][s]=0;
1203
 
 
1204
 
  handRelFirst=posPoint->handRelFirst;
1205
 
  noOfStartMoves=handRelFirst;
1206
 
 
1207
 
  for (k=0; k<=2; k++) {
1208
 
    hand[k]=handId(first, k);
1209
 
    suit[k]=startMoves[k].suit;
1210
 
    rank[k]=startMoves[k].rank;
1211
 
    if (k<noOfStartMoves)
1212
 
      startMovesBitMap[hand[k]][suit[k]]|=bitMapRank[rank[k]];
1213
 
  }
1214
 
 
1215
 
  for (d=0; d<=49; d++) {
1216
 
    /*bestMove[d].suit=0;*/
1217
 
    localVar[thrId].bestMove[d].rank=0;
1218
 
    localVar[thrId].bestMoveTT[d].rank=0;
1219
 
    /*bestMove[d].weight=0;
1220
 
    bestMove[d].sequence=0; 0315 */
1221
 
  }
1222
 
 
1223
 
  if (((handId(first, handRelFirst))==0)||
1224
 
    ((handId(first, handRelFirst))==2)) {
1225
 
    localVar[thrId].nodeTypeStore[0]=MAXNODE;
1226
 
    localVar[thrId].nodeTypeStore[1]=MINNODE;
1227
 
    localVar[thrId].nodeTypeStore[2]=MAXNODE;
1228
 
    localVar[thrId].nodeTypeStore[3]=MINNODE;
1229
 
  }
1230
 
  else {
1231
 
    localVar[thrId].nodeTypeStore[0]=MINNODE;
1232
 
    localVar[thrId].nodeTypeStore[1]=MAXNODE;
1233
 
    localVar[thrId].nodeTypeStore[2]=MINNODE;
1234
 
    localVar[thrId].nodeTypeStore[3]=MAXNODE;
1235
 
  }
1236
 
 
1237
 
  k=noOfStartMoves;
1238
 
  posPoint->first[depth]=first;
1239
 
  posPoint->handRelFirst=k;
1240
 
  assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
1241
 
  posPoint->tricksMAX=0;
1242
 
 
1243
 
  if (k>0) {
1244
 
    posPoint->move[depth+k]=startMoves[k-1];
1245
 
    move=startMoves[k-1];
1246
 
  }
1247
 
 
1248
 
  posPoint->high[depth+k]=first;
1249
 
 
1250
 
  while (k>0) {
1251
 
    localVar[thrId].movePly[depth+k].current=0;
1252
 
    localVar[thrId].movePly[depth+k].last=0;
1253
 
    localVar[thrId].movePly[depth+k].move[0].suit=startMoves[k-1].suit;
1254
 
    localVar[thrId].movePly[depth+k].move[0].rank=startMoves[k-1].rank;
1255
 
    if (k<noOfStartMoves) {     /* If there is more than one start move */
1256
 
      if (WinningMove(&startMoves[k-1], &move, localVar[thrId].trump, thrId)) {
1257
 
        posPoint->move[depth+k].suit=startMoves[k-1].suit;
1258
 
        posPoint->move[depth+k].rank=startMoves[k-1].rank;
1259
 
        posPoint->high[depth+k]=handId(first, noOfStartMoves-k);
1260
 
        move=posPoint->move[depth+k];
1261
 
      }
1262
 
      else {
1263
 
        posPoint->move[depth+k]=posPoint->move[depth+k+1];
1264
 
        posPoint->high[depth+k]=posPoint->high[depth+k+1];
1265
 
      }
1266
 
    }
1267
 
    k--;
1268
 
  }
1269
 
 
1270
 
  for (s=0; s<=3; s++)
1271
 
    posPoint->removedRanks[s]=0;
1272
 
 
1273
 
  for (s=0; s<=3; s++)       /* Suit */
1274
 
    for (h=0; h<=3; h++)     /* Hand */
1275
 
      posPoint->removedRanks[s]|=
1276
 
        posPoint->rankInSuit[h][s];
1277
 
  for (s=0; s<=3; s++)
1278
 
    posPoint->removedRanks[s]=~(posPoint->removedRanks[s]);
1279
 
 
1280
 
  for (s=0; s<=3; s++)       /* Suit */
1281
 
    for (h=0; h<=3; h++)     /* Hand */
1282
 
      posPoint->removedRanks[s]&=
1283
 
        (~startMovesBitMap[h][s]);
1284
 
 
1285
 
  for (s=0; s<=3; s++)
1286
 
    localVar[thrId].iniRemovedRanks[s]=posPoint->removedRanks[s];
1287
 
 
1288
 
  /*for (d=0; d<=49; d++) {
1289
 
    for (s=0; s<=3; s++)
1290
 
      posPoint->winRanks[d][s]=0;
1291
 
  }*/
1292
 
 
1293
 
  /* Initialize winning and second best ranks */
1294
 
  for (s=0; s<=3; s++) {
1295
 
    maxAgg=0;
1296
 
    for (h=0; h<=3; h++) {
1297
 
      aggHand[h][s]=startMovesBitMap[h][s] | localVar[thrId].game.suit[h][s];
1298
 
      if (aggHand[h][s]>maxAgg) {
1299
 
         maxAgg=aggHand[h][s];
1300
 
         maxHand=h;
1301
 
      }
1302
 
    }
1303
 
    if (maxAgg!=0) {
1304
 
      posPoint->winner[s].hand=maxHand;
1305
 
      k=highestRank[aggHand[maxHand][s]];
1306
 
      posPoint->winner[s].rank=k;
1307
 
 
1308
 
      maxAgg=0;
1309
 
      for (h=0; h<=3; h++) {
1310
 
        aggHand[h][s]&=(~bitMapRank[k]);
1311
 
        if (aggHand[h][s]>maxAgg) {
1312
 
          maxAgg=aggHand[h][s];
1313
 
          maxHand=h;
1314
 
        }
1315
 
      }
1316
 
      if (maxAgg>0) {
1317
 
         posPoint->secondBest[s].hand=maxHand;
1318
 
         posPoint->secondBest[s].rank=highestRank[aggHand[maxHand][s]];
1319
 
      }
1320
 
      else {
1321
 
        posPoint->secondBest[s].hand=-1;
1322
 
        posPoint->secondBest[s].rank=0;
1323
 
      }
1324
 
    }
1325
 
    else {
1326
 
      posPoint->winner[s].hand=-1;
1327
 
      posPoint->winner[s].rank=0;
1328
 
      posPoint->secondBest[s].hand=-1;
1329
 
      posPoint->secondBest[s].rank=0;
1330
 
    }
1331
 
  }
1332
 
 
1333
 
 
1334
 
  for (s=0; s<=3; s++)
1335
 
    for (h=0; h<=3; h++)
1336
 
      posPoint->length[h][s]=
1337
 
        (unsigned char)counttable[posPoint->rankInSuit[h][s]];
1338
 
 
1339
 
  #ifdef STAT
1340
 
  for (d=0; d<=49; d++) {
1341
 
    score1Counts[d]=0;
1342
 
    score0Counts[d]=0;
1343
 
    c1[d]=0;  c2[d]=0;  c3[d]=0;  c4[d]=0;  c5[d]=0;  c6[d]=0; c7[d]=0;
1344
 
    c8[d]=0;
1345
 
    localVar[thrId].no[d]=0;
1346
 
  }
1347
 
  #endif
1348
 
 
1349
 
  if (!mtd) {
1350
 
    localVar[thrId].lenSetSize=0;
1351
 
    for (k=0; k<=13; k++) {
1352
 
      for (h=0; h<=3; h++) {
1353
 
        localVar[thrId].rootnp[k][h]=&localVar[thrId].posSearch[localVar[thrId].lenSetSize];
1354
 
        localVar[thrId].posSearch[localVar[thrId].lenSetSize].suitLengths=0;
1355
 
        localVar[thrId].posSearch[localVar[thrId].lenSetSize].posSearchPoint=NULL;
1356
 
        localVar[thrId].posSearch[localVar[thrId].lenSetSize].left=NULL;
1357
 
        localVar[thrId].posSearch[localVar[thrId].lenSetSize].right=NULL;
1358
 
        localVar[thrId].lenSetSize++;
1359
 
      }
1360
 
    }
1361
 
    localVar[thrId].nodeSetSize=0;
1362
 
    localVar[thrId].winSetSize=0;
1363
 
  }
1364
 
 
1365
 
  #ifdef TTDEBUG
1366
 
  if (!suppressTTlog)
1367
 
    lastTTstore=0;
1368
 
  #endif
1369
 
 
1370
 
  return;
1371
 
}
1372
 
 
1373
 
#ifdef STAT
1374
 
int score1Counts[50], score0Counts[50];
1375
 
int sumScore1Counts, sumScore0Counts, dd, suit, rank, order;
1376
 
int c1[50], c2[50], c3[50], c4[50], c5[50], c6[50], c7[50], c8[50], c9[50];
1377
 
int sumc1, sumc2, sumc3, sumc4, sumc5, sumc6, sumc7, sumc8, sumc9;
1378
 
#endif
1379
 
 
1380
 
int ABsearch(struct pos * posPoint, int target, int depth, int thrId) {
1381
 
    /* posPoint points to the current look-ahead position,
1382
 
       target is number of tricks to take for the player,
1383
 
       depth is the remaining search length, must be positive,
1384
 
       the value of the subtree is returned.  */
1385
 
 
1386
 
  int moveExists, mexists, value, hand, scoreFlag, found, trump;
1387
 
  int ready, hfirst, hh, ss, rr, mcurrent, qtricks, tricks, res, k;
1388
 
  unsigned short int makeWinRank[4];
1389
 
  struct nodeCardsType * cardsP;
1390
 
  struct evalType evalData;
1391
 
  struct winCardType * np;
1392
 
  struct posSearchType * pp;
1393
 
  struct nodeCardsType  * tempP;
1394
 
  struct movePlyType *mply;
1395
 
  unsigned short int aggr[4];
1396
 
  unsigned short int ranks;
1397
 
  long long suitLengths;
1398
 
 
1399
 
  struct evalType Evaluate(struct pos * posPoint, int trump, int thrId);
1400
 
  void Make(struct pos * posPoint, unsigned short int trickCards[4],
1401
 
    int depth, int trump, struct movePlyType *mply, int thrId);
1402
 
  void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId);
1403
 
 
1404
 
  /*cardsP=NULL;*/
1405
 
  assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
1406
 
  trump=localVar[thrId].trump;
1407
 
  hand=handId(posPoint->first[depth], posPoint->handRelFirst);
1408
 
  localVar[thrId].nodes++;
1409
 
  if (posPoint->handRelFirst==0) {
1410
 
    localVar[thrId].trickNodes++;
1411
 
    if (posPoint->tricksMAX>=target) {
1412
 
      for (ss=0; ss<=3; ss++)
1413
 
        posPoint->winRanks[depth][ss]=0;
1414
 
 
1415
 
        #ifdef STAT
1416
 
        c1[depth]++;
1417
 
 
1418
 
        score1Counts[depth]++;
1419
 
        if (depth==localVar[thrId].iniDepth) {
1420
 
          fprintf(localVar[thrId].fp2, "score statistics:\n");
1421
 
          for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1422
 
            fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1423
 
            score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],
1424
 
              c3[dd], c4[dd]);
1425
 
            fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1426
 
              c6[dd], c7[dd], c8[dd]);
1427
 
          }
1428
 
        }
1429
 
        #endif
1430
 
 
1431
 
      return TRUE;
1432
 
    }
1433
 
    if (((posPoint->tricksMAX+(depth>>2)+1)<target)/*&&(depth>0)*/) {
1434
 
      for (ss=0; ss<=3; ss++)
1435
 
        posPoint->winRanks[depth][ss]=0;
1436
 
 
1437
 
 #ifdef STAT
1438
 
        c2[depth]++;
1439
 
        score0Counts[depth]++;
1440
 
        if (depth==localVar[thrId].iniDepth) {
1441
 
          fprintf(localVar[thrId].fp2, "score statistics:\n");
1442
 
          for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1443
 
            fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1444
 
            score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],
1445
 
              c3[dd], c4[dd]);
1446
 
            fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1447
 
              c6[dd], c7[dd], c8[dd]);
1448
 
          }
1449
 
        }
1450
 
 #endif
1451
 
 
1452
 
      return FALSE;
1453
 
    }
1454
 
 
1455
 
    if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) {
1456
 
      qtricks=QuickTricks(posPoint, hand, depth, target, trump, &res, thrId);
1457
 
      if (res) {
1458
 
        if (qtricks==0)
1459
 
          return FALSE;
1460
 
        else
1461
 
          return TRUE;
1462
 
 #ifdef STAT
1463
 
          c3[depth]++;
1464
 
          score1Counts[depth]++;
1465
 
          if (depth==localVar[thrId].iniDepth) {
1466
 
            fprintf(localVar[thrId].fp2, "score statistics:\n");
1467
 
            for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1468
 
              fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1469
 
              score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],
1470
 
                c3[dd], c4[dd]);
1471
 
              fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1472
 
                c6[dd], c7[dd], c8[dd]);
1473
 
            }
1474
 
          }
1475
 
 #endif
1476
 
      }
1477
 
      if (!LaterTricksMIN(posPoint,hand,depth,target,trump,thrId))
1478
 
        return FALSE;
1479
 
    }
1480
 
    else {
1481
 
      qtricks=QuickTricks(posPoint, hand, depth, target, trump, &res, thrId);
1482
 
      if (res) {
1483
 
        if (qtricks==0)
1484
 
          return TRUE;
1485
 
        else
1486
 
          return FALSE;
1487
 
 #ifdef STAT
1488
 
          c4[depth]++;
1489
 
          score0Counts[depth]++;
1490
 
          if (depth==localVar[thrId].iniDepth) {
1491
 
            fprintf(localVar[thrId].fp2, "score statistics:\n");
1492
 
            for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1493
 
              fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1494
 
              score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],
1495
 
                c3[dd], c4[dd]);
1496
 
              fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1497
 
                c6[dd], c7[dd], c8[dd]);
1498
 
            }
1499
 
          }
1500
 
 #endif
1501
 
      }
1502
 
      if (LaterTricksMAX(posPoint,hand,depth,target,trump,thrId))
1503
 
        return TRUE;
1504
 
    }
1505
 
  }
1506
 
 
1507
 
  else if (posPoint->handRelFirst==1) {
1508
 
    ss=posPoint->move[depth+1].suit;
1509
 
    ranks=posPoint->rankInSuit[hand][ss] |
1510
 
      posPoint->rankInSuit[partner[hand]][ss];
1511
 
    found=FALSE; rr=0; qtricks=0;
1512
 
 
1513
 
    if ((trump!=4) && (ss!=trump) &&
1514
 
      (((posPoint->rankInSuit[hand][ss]==0)
1515
 
          && (posPoint->rankInSuit[hand][trump]!=0))||
1516
 
          ((posPoint->rankInSuit[partner[hand]][ss]==0)
1517
 
          && (posPoint->rankInSuit[partner[hand]][trump]!=0))))  {
1518
 
          /* Own side can ruff */
1519
 
      if ((posPoint->rankInSuit[lho[hand]][ss]!=0)||
1520
 
         (posPoint->rankInSuit[lho[hand]][trump]==0)) {
1521
 
        found=TRUE;
1522
 
        qtricks=1;
1523
 
      }
1524
 
    }
1525
 
 
1526
 
    else if ( ranks >(bitMapRank[posPoint->move[depth+1].rank] |
1527
 
          posPoint->rankInSuit[lho[hand]][ss])) {
1528
 
          /* Own side has highest card in suit */
1529
 
      if ((trump==4) || ((ss==trump)||
1530
 
        (posPoint->rankInSuit[lho[hand]][trump]==0)
1531
 
             || (posPoint->rankInSuit[lho[hand]][ss]!=0))) {
1532
 
        rr=highestRank[ranks];
1533
 
        if (rr!=0) {
1534
 
          found=TRUE;
1535
 
          qtricks=1;
1536
 
        }
1537
 
        else
1538
 
          found=FALSE;
1539
 
      }
1540
 
    }
1541
 
 
1542
 
    if ((found)&&(depth!=localVar[thrId].iniDepth)) {
1543
 
      for (k=0; k<=3; k++)
1544
 
        posPoint->winRanks[depth][k]=0;
1545
 
        if (rr!=0)
1546
 
          posPoint->winRanks[depth][ss]=bitMapRank[rr];
1547
 
 
1548
 
      if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) {
1549
 
        if (posPoint->tricksMAX+qtricks>=target) {
1550
 
          return TRUE;
1551
 
        }
1552
 
        else if (trump==4) {
1553
 
          if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss])
1554
 
            hh=hand;    /* Hand to lead next trick */
1555
 
          else
1556
 
            hh=partner[hand];
1557
 
 
1558
 
          if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&&
1559
 
                (posPoint->secondBest[ss].hand==hh)) {
1560
 
            qtricks++;
1561
 
            posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank];
1562
 
            if (posPoint->tricksMAX+qtricks>=target) {
1563
 
              return TRUE;
1564
 
            }
1565
 
          }
1566
 
 
1567
 
          for (k=0; k<=3; k++) {
1568
 
            if ((k!=ss)&&(posPoint->length[hh][k]!=0))  {       /* Not lead suit, not void in suit */
1569
 
              if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0)
1570
 
                &&(posPoint->length[partner[hh]][k]==0)) {
1571
 
                qtricks+=counttable[posPoint->rankInSuit[hh][k]];
1572
 
                if (posPoint->tricksMAX+qtricks>=target) {
1573
 
                  return TRUE;
1574
 
                }
1575
 
              }
1576
 
              else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) {
1577
 
                qtricks++;
1578
 
                posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank];
1579
 
                if (posPoint->tricksMAX+qtricks>=target) {
1580
 
                  return TRUE;
1581
 
                }
1582
 
              }
1583
 
            }
1584
 
          }
1585
 
        }
1586
 
      }
1587
 
      else {
1588
 
        /* MIN node */
1589
 
        if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) {
1590
 
          return FALSE;
1591
 
        }
1592
 
        else if (trump==4) {
1593
 
          if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss])
1594
 
            hh=hand;    /* Hand to lead next trick */
1595
 
          else
1596
 
            hh=partner[hand];
1597
 
 
1598
 
          if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&&
1599
 
             (posPoint->secondBest[ss].hand==hh)) {
1600
 
            qtricks++;
1601
 
            posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank];
1602
 
            if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) {
1603
 
              return FALSE;
1604
 
            }
1605
 
          }
1606
 
 
1607
 
          for (k=0; k<=3; k++) {
1608
 
            if ((k!=ss)&&(posPoint->length[hh][k]!=0))  {       /* Not lead suit, not void in suit */
1609
 
              if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0)
1610
 
                  &&(posPoint->length[partner[hh]][k]==0)) {
1611
 
                qtricks+=counttable[posPoint->rankInSuit[hh][k]];
1612
 
                if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) {
1613
 
                  return FALSE;
1614
 
                }
1615
 
              }
1616
 
              else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) {
1617
 
                qtricks++;
1618
 
                posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank];
1619
 
                if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) {
1620
 
                  return FALSE;
1621
 
                }
1622
 
              }
1623
 
            }
1624
 
          }
1625
 
        }
1626
 
      }
1627
 
    }
1628
 
  }
1629
 
 
1630
 
  if ((posPoint->handRelFirst==0)&&
1631
 
    (depth!=localVar[thrId].iniDepth)) {
1632
 
    for (ss=0; ss<=3; ss++) {
1633
 
      aggr[ss]=0;
1634
 
      for (hh=0; hh<=3; hh++)
1635
 
        aggr[ss]|=posPoint->rankInSuit[hh][ss];
1636
 
      posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss];
1637
 
    }
1638
 
    tricks=depth>>2;
1639
 
    suitLengths=0;
1640
 
    for (ss=0; ss<=2; ss++)
1641
 
      for (hh=0; hh<=3; hh++) {
1642
 
        suitLengths<<=4;
1643
 
        suitLengths|=posPoint->length[hh][ss];
1644
 
      }
1645
 
 
1646
 
    pp=SearchLenAndInsert(localVar[thrId].rootnp[tricks][hand],
1647
 
         suitLengths, FALSE, &res, thrId);
1648
 
        /* Find node that fits the suit lengths */
1649
 
    if (pp!=NULL) {
1650
 
      np=pp->posSearchPoint;
1651
 
      if (np==NULL)
1652
 
        cardsP=NULL;
1653
 
      else
1654
 
        cardsP=FindSOP(posPoint, np, hand, target, tricks, &scoreFlag, thrId);
1655
 
 
1656
 
      if (cardsP!=NULL) {
1657
 
        if (scoreFlag==1) {
1658
 
          for (ss=0; ss<=3; ss++)
1659
 
            posPoint->winRanks[depth][ss]=
1660
 
              localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)cardsP->leastWin[ss]];
1661
 
 
1662
 
          if (cardsP->bestMoveRank!=0) {
1663
 
            localVar[thrId].bestMoveTT[depth].suit=cardsP->bestMoveSuit;
1664
 
            localVar[thrId].bestMoveTT[depth].rank=cardsP->bestMoveRank;
1665
 
          }
1666
 
 #ifdef STAT
1667
 
          c5[depth]++;
1668
 
          if (scoreFlag==1)
1669
 
            score1Counts[depth]++;
1670
 
          else
1671
 
            score0Counts[depth]++;
1672
 
          if (depth==localVar[thrId].iniDepth) {
1673
 
            fprintf(localVar[thrId].fp2, "score statistics:\n");
1674
 
            for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1675
 
              fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1676
 
                score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],c3[dd], c4[dd]);
1677
 
              fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1678
 
                c6[dd], c7[dd], c8[dd]);
1679
 
            }
1680
 
          }
1681
 
 #endif
1682
 
 #ifdef TTDEBUG
1683
 
          if (!suppressTTlog) {
1684
 
            if (lastTTstore<SEARCHSIZE)
1685
 
              ReceiveTTstore(posPoint, cardsP, target, depth, thrId);
1686
 
            else
1687
 
              ttCollect=FALSE;
1688
 
          }
1689
 
 #endif
1690
 
          return TRUE;
1691
 
        }
1692
 
        else {
1693
 
          for (ss=0; ss<=3; ss++)
1694
 
            posPoint->winRanks[depth][ss]=
1695
 
              localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)cardsP->leastWin[ss]];
1696
 
 
1697
 
          if (cardsP->bestMoveRank!=0) {
1698
 
            localVar[thrId].bestMoveTT[depth].suit=cardsP->bestMoveSuit;
1699
 
            localVar[thrId].bestMoveTT[depth].rank=cardsP->bestMoveRank;
1700
 
          }
1701
 
 #ifdef STAT
1702
 
          c6[depth]++;
1703
 
          if (scoreFlag==1)
1704
 
            score1Counts[depth]++;
1705
 
          else
1706
 
            score0Counts[depth]++;
1707
 
          if (depth==localVar[thrId].iniDepth) {
1708
 
            fprintf(localVar[thrId].fp2, "score statistics:\n");
1709
 
            for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1710
 
              fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1711
 
                score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd],
1712
 
                  c4[dd]);
1713
 
              fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1714
 
                  c6[dd], c7[dd], c8[dd]);
1715
 
            }
1716
 
          }
1717
 
 #endif
1718
 
 
1719
 
 #ifdef TTDEBUG
1720
 
          if (!suppressTTlog) {
1721
 
            if (lastTTstore<SEARCHSIZE)
1722
 
              ReceiveTTstore(posPoint, cardsP, target, depth, thrId);
1723
 
            else
1724
 
              ttCollect=FALSE;
1725
 
          }
1726
 
 #endif
1727
 
          return FALSE;
1728
 
        }
1729
 
      }
1730
 
    }
1731
 
  }
1732
 
 
1733
 
  if (depth==0) {                    /* Maximum depth? */
1734
 
    evalData=Evaluate(posPoint, trump, thrId);        /* Leaf node */
1735
 
    if (evalData.tricks>=target)
1736
 
      value=TRUE;
1737
 
    else
1738
 
      value=FALSE;
1739
 
    for (ss=0; ss<=3; ss++) {
1740
 
      posPoint->winRanks[depth][ss]=evalData.winRanks[ss];
1741
 
 
1742
 
 #ifdef STAT
1743
 
        c7[depth]++;
1744
 
        if (value==1)
1745
 
          score1Counts[depth]++;
1746
 
        else
1747
 
          score0Counts[depth]++;
1748
 
        if (depth==localVar[thrId].iniDepth) {
1749
 
          fprintf(localVar[thrId].fp2, "score statistics:\n");
1750
 
          for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1751
 
            fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1752
 
              score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd],
1753
 
              c4[dd]);
1754
 
            fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1755
 
              c6[dd], c7[dd], c8[dd]);
1756
 
          }
1757
 
        }
1758
 
 #endif
1759
 
    }
1760
 
    return value;
1761
 
  }
1762
 
  else {
1763
 
    mply=&localVar[thrId].movePly[depth];
1764
 
    moveExists=MoveGen(posPoint, depth, trump, mply, thrId);
1765
 
 
1766
 
/*#if 0*/
1767
 
    if ((posPoint->handRelFirst==3)&&(depth>=/*29*/33/*37*/)
1768
 
        &&(depth!=localVar[thrId].iniDepth)) {
1769
 
    /*localVar[thrId].movePly[depth].current=0;*/
1770
 
      mply->current=0;
1771
 
      mexists=TRUE;
1772
 
      ready=FALSE;
1773
 
      while (mexists) {
1774
 
        Make(posPoint, makeWinRank, depth, trump, mply, thrId);
1775
 
        depth--;
1776
 
 
1777
 
        for (ss=0; ss<=3; ss++) {
1778
 
          aggr[ss]=0;
1779
 
          for (hh=0; hh<=3; hh++)
1780
 
            aggr[ss]|=posPoint->rankInSuit[hh][ss];
1781
 
          posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss];
1782
 
        }
1783
 
        tricks=depth>>2;
1784
 
        hfirst=posPoint->first[depth];
1785
 
        suitLengths=0;
1786
 
        for (ss=0; ss<=2; ss++)
1787
 
          for (hh=0; hh<=3; hh++) {
1788
 
            suitLengths<<=4;
1789
 
            suitLengths|=posPoint->length[hh][ss];
1790
 
          }
1791
 
 
1792
 
        pp=SearchLenAndInsert(localVar[thrId].rootnp[tricks][hfirst],
1793
 
          suitLengths, FALSE, &res, thrId);
1794
 
        /* Find node that fits the suit lengths */
1795
 
        if (pp!=NULL) {
1796
 
          np=pp->posSearchPoint;
1797
 
          if (np==NULL)
1798
 
            tempP=NULL;
1799
 
          else
1800
 
            tempP=FindSOP(posPoint, np, hfirst, target, tricks, &scoreFlag, thrId);
1801
 
 
1802
 
          if (tempP!=NULL) {
1803
 
            if ((localVar[thrId].nodeTypeStore[hand]==MAXNODE)&&(scoreFlag==1)) {
1804
 
              for (ss=0; ss<=3; ss++)
1805
 
                posPoint->winRanks[depth+1][ss]=
1806
 
                  localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)tempP->leastWin[ss]];
1807
 
              if (tempP->bestMoveRank!=0) {
1808
 
                localVar[thrId].bestMoveTT[depth+1].suit=tempP->bestMoveSuit;
1809
 
                localVar[thrId].bestMoveTT[depth+1].rank=tempP->bestMoveRank;
1810
 
              }
1811
 
              for (ss=0; ss<=3; ss++)
1812
 
                posPoint->winRanks[depth+1][ss]|=makeWinRank[ss];
1813
 
              Undo(posPoint, depth+1, &localVar[thrId].movePly[depth+1],thrId);
1814
 
              return TRUE;
1815
 
            }
1816
 
            else if ((localVar[thrId].nodeTypeStore[hand]==MINNODE)&&(scoreFlag==0)) {
1817
 
              for (ss=0; ss<=3; ss++)
1818
 
                posPoint->winRanks[depth+1][ss]=
1819
 
                  localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)tempP->leastWin[ss]];
1820
 
              if (tempP->bestMoveRank!=0) {
1821
 
                localVar[thrId].bestMoveTT[depth+1].suit=tempP->bestMoveSuit;
1822
 
                localVar[thrId].bestMoveTT[depth+1].rank=tempP->bestMoveRank;
1823
 
              }
1824
 
              for (ss=0; ss<=3; ss++)
1825
 
                posPoint->winRanks[depth+1][ss]|=makeWinRank[ss];
1826
 
              Undo(posPoint, depth+1, &localVar[thrId].movePly[depth+1], thrId);
1827
 
                return FALSE;
1828
 
            }
1829
 
            else {
1830
 
              localVar[thrId].movePly[depth+1].move[localVar[thrId].movePly[depth+1].current].weight+=100;
1831
 
              ready=TRUE;
1832
 
            }
1833
 
          }
1834
 
        }
1835
 
        depth++;
1836
 
        Undo(posPoint, depth, mply, thrId);
1837
 
        if (ready)
1838
 
          break;
1839
 
 
1840
 
        if (mply->current <= (mply->last-1)) {
1841
 
          mply->current++;
1842
 
          mexists=TRUE;
1843
 
        }
1844
 
        else
1845
 
          mexists=FALSE;
1846
 
      }
1847
 
      if (ready)
1848
 
        MergeSort(mply->last+1, mply->move);
1849
 
    }
1850
 
/*#endif*/
1851
 
 
1852
 
 
1853
 
    mply->current=0;
1854
 
    if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) {
1855
 
      value=FALSE;
1856
 
      for (ss=0; ss<=3; ss++)
1857
 
        posPoint->winRanks[depth][ss]=0;
1858
 
 
1859
 
      while (moveExists)  {
1860
 
        Make(posPoint, makeWinRank, depth, trump, mply, thrId);        /* Make current move */
1861
 
 
1862
 
        assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
1863
 
        value=ABsearch(posPoint, target, depth-1, thrId);
1864
 
 
1865
 
        Undo(posPoint, depth, mply, thrId);      /* Retract current move */
1866
 
        if (value==TRUE) {
1867
 
        /* A cut-off? */
1868
 
          for (ss=0; ss<=3; ss++)
1869
 
            posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] |
1870
 
              makeWinRank[ss];
1871
 
          mcurrent=mply->current;
1872
 
          localVar[thrId].bestMove[depth]=mply->move[mcurrent];
1873
 
          goto ABexit;
1874
 
        }
1875
 
        for (ss=0; ss<=3; ss++)
1876
 
          posPoint->winRanks[depth][ss]=posPoint->winRanks[depth][ss] |
1877
 
            posPoint->winRanks[depth-1][ss] | makeWinRank[ss];
1878
 
 
1879
 
        moveExists=NextMove(posPoint, depth, mply, thrId);
1880
 
      }
1881
 
    }
1882
 
    else {                          /* A minnode */
1883
 
      value=TRUE;
1884
 
      for (ss=0; ss<=3; ss++)
1885
 
        posPoint->winRanks[depth][ss]=0;
1886
 
 
1887
 
      while (moveExists)  {
1888
 
        Make(posPoint, makeWinRank, depth, trump, mply, thrId);        /* Make current move */
1889
 
 
1890
 
        value=ABsearch(posPoint, target, depth-1, thrId);
1891
 
 
1892
 
        Undo(posPoint, depth, mply, thrId);       /* Retract current move */
1893
 
        if (value==FALSE) {
1894
 
        /* A cut-off? */
1895
 
          for (ss=0; ss<=3; ss++)
1896
 
            posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] |
1897
 
              makeWinRank[ss];
1898
 
          mcurrent=mply->current;
1899
 
          localVar[thrId].bestMove[depth]=mply->move[mcurrent];
1900
 
          goto ABexit;
1901
 
        }
1902
 
        for (ss=0; ss<=3; ss++)
1903
 
          posPoint->winRanks[depth][ss]=posPoint->winRanks[depth][ss] |
1904
 
            posPoint->winRanks[depth-1][ss] | makeWinRank[ss];
1905
 
 
1906
 
        moveExists=NextMove(posPoint, depth, mply, thrId);
1907
 
      }
1908
 
    }
1909
 
  }
1910
 
  ABexit:
1911
 
  if (depth>=4) {
1912
 
    if(posPoint->handRelFirst==0) {
1913
 
      tricks=depth>>2;
1914
 
      if (value)
1915
 
        k=target;
1916
 
      else
1917
 
        k=target-1;
1918
 
      if (depth!=localVar[thrId].iniDepth)
1919
 
        BuildSOP(posPoint, tricks, hand, target, depth,
1920
 
          value, k, thrId);
1921
 
      if (localVar[thrId].clearTTflag) {
1922
 
         /* Wipe out the TT dynamically allocated structures
1923
 
            except for the initially allocated structures.
1924
 
            Set the TT limits to the initial values.
1925
 
            Reset TT array indices to zero.
1926
 
            Reset memory chunk indices to zero.
1927
 
            Set allocated memory to the initial value. */
1928
 
        /*localVar[thrId].fp2=fopen("dyn.txt", "a");
1929
 
        fprintf(localVar[thrId].fp2, "Clear TT:\n");
1930
 
        fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n",
1931
 
               wcount, ncount, lcount);
1932
 
        fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n",
1933
 
               winSetSize, nodeSetSize, lenSetSize);
1934
 
        fprintf(localVar[thrId].fp2, "\n");
1935
 
        fclose(localVar[thrId].fp2);*/
1936
 
 
1937
 
        Wipe(thrId);
1938
 
        localVar[thrId].winSetSizeLimit=WINIT;
1939
 
        localVar[thrId].nodeSetSizeLimit=NINIT;
1940
 
        localVar[thrId].lenSetSizeLimit=LINIT;
1941
 
        localVar[thrId].lcount=0;
1942
 
        localVar[thrId].allocmem=(localVar[thrId].lenSetSizeLimit+1)*sizeof(struct posSearchType);
1943
 
        localVar[thrId].lenSetSize=0;
1944
 
        localVar[thrId].posSearch=localVar[thrId].pl[localVar[thrId].lcount];
1945
 
        for (k=0; k<=13; k++) {
1946
 
          for (hh=0; hh<=3; hh++) {
1947
 
            localVar[thrId].rootnp[k][hh]=&localVar[thrId].posSearch[localVar[thrId].lenSetSize];
1948
 
            localVar[thrId].posSearch[localVar[thrId].lenSetSize].suitLengths=0;
1949
 
            localVar[thrId].posSearch[localVar[thrId].lenSetSize].posSearchPoint=NULL;
1950
 
            localVar[thrId].posSearch[localVar[thrId].lenSetSize].left=NULL;
1951
 
            localVar[thrId].posSearch[localVar[thrId].lenSetSize].right=NULL;
1952
 
            localVar[thrId].lenSetSize++;
1953
 
          }
1954
 
        }
1955
 
        localVar[thrId].nodeSetSize=0;
1956
 
        localVar[thrId].winSetSize=0;
1957
 
        localVar[thrId].wcount=0; localVar[thrId].ncount=0;
1958
 
        localVar[thrId].allocmem+=(localVar[thrId].winSetSizeLimit+1)*sizeof(struct winCardType);
1959
 
        localVar[thrId].winCards=localVar[thrId].pw[localVar[thrId].wcount];
1960
 
        localVar[thrId].allocmem+=(localVar[thrId].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType);
1961
 
        localVar[thrId].nodeCards=localVar[thrId].pn[localVar[thrId].ncount];
1962
 
        localVar[thrId].clearTTflag=FALSE;
1963
 
        localVar[thrId].windex=-1;
1964
 
      }
1965
 
    }
1966
 
  }
1967
 
 
1968
 
 #ifdef STAT
1969
 
  c8[depth]++;
1970
 
  if (value==1)
1971
 
    score1Counts[depth]++;
1972
 
  else
1973
 
    score0Counts[depth]++;
1974
 
  if (depth==localVar[thrId].iniDepth) {
1975
 
    if (localVar[thrId].fp2==NULL)
1976
 
      exit(0);
1977
 
    fprintf(localVar[thrId].fp2, "\n");
1978
 
    fprintf(localVar[thrId].fp2, "top level cards:\n");
1979
 
    for (hh=0; hh<=3; hh++) {
1980
 
      fprintf(localVar[thrId].fp2, "hand=%c\n", cardHand[hh]);
1981
 
      for (ss=0; ss<=3; ss++) {
1982
 
        fprintf(localVar[thrId].fp2, "suit=%c", cardSuit[ss]);
1983
 
        for (rr=14; rr>=2; rr--)
1984
 
          if (posPoint->rankInSuit[hh][ss] & bitMapRank[rr])
1985
 
            fprintf(localVar[thrId].fp2, " %c", cardRank[rr]);
1986
 
        fprintf(localVar[thrId].fp2, "\n");
1987
 
      }
1988
 
      fprintf(localVar[thrId].fp2, "\n");
1989
 
    }
1990
 
    fprintf(localVar[thrId].fp2, "top level winning cards:\n");
1991
 
    for (ss=0; ss<=3; ss++) {
1992
 
      fprintf(localVar[thrId].fp2, "suit=%c", cardSuit[ss]);
1993
 
      for (rr=14; rr>=2; rr--)
1994
 
        if (posPoint->winRanks[depth][ss] & bitMapRank[rr])
1995
 
          fprintf(localVar[thrId].fp2, " %c", cardRank[rr]);
1996
 
      fprintf(localVar[thrId].fp2, "\n");
1997
 
    }
1998
 
    fprintf(localVar[thrId].fp2, "\n");
1999
 
    fprintf(localVar[thrId].fp2, "\n");
2000
 
 
2001
 
    fprintf(localVar[thrId].fp2, "score statistics:\n");
2002
 
    sumScore0Counts=0;
2003
 
    sumScore1Counts=0;
2004
 
    sumc1=0; sumc2=0; sumc3=0; sumc4=0;
2005
 
    sumc5=0; sumc6=0; sumc7=0; sumc8=0; sumc9=0;
2006
 
    for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
2007
 
      fprintf(localVar[thrId].fp2, "depth=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
2008
 
          score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], c4[dd]);
2009
 
      fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd],
2010
 
          c7[dd], c8[dd]);
2011
 
      sumScore0Counts=sumScore0Counts+score0Counts[dd];
2012
 
      sumScore1Counts=sumScore1Counts+score1Counts[dd];
2013
 
      sumc1=sumc1+c1[dd];
2014
 
      sumc2=sumc2+c2[dd];
2015
 
      sumc3=sumc3+c3[dd];
2016
 
      sumc4=sumc4+c4[dd];
2017
 
      sumc5=sumc5+c5[dd];
2018
 
      sumc6=sumc6+c6[dd];
2019
 
      sumc7=sumc7+c7[dd];
2020
 
      sumc8=sumc8+c8[dd];
2021
 
      sumc9=sumc9+c9[dd];
2022
 
    }
2023
 
    fprintf(localVar[thrId].fp2, "\n");
2024
 
    fprintf(localVar[thrId].fp2, "score sum statistics:\n");
2025
 
    fprintf(localVar[thrId].fp2, "\n");
2026
 
    fprintf(localVar[thrId].fp2, "sumScore0Counts=%d sumScore1Counts=%d\n",
2027
 
        sumScore0Counts, sumScore1Counts);
2028
 
    fprintf(localVar[thrId].fp2, "nodeSetSize=%d  winSetSize=%d\n", localVar[thrId].nodeSetSize,
2029
 
        localVar[thrId].winSetSize);
2030
 
    fprintf(localVar[thrId].fp2, "sumc1=%d sumc2=%d sumc3=%d sumc4=%d\n",
2031
 
        sumc1, sumc2, sumc3, sumc4);
2032
 
    fprintf(localVar[thrId].fp2, "sumc5=%d sumc6=%d sumc7=%d sumc8=%d sumc9=%d\n",
2033
 
        sumc5, sumc6, sumc7, sumc8, sumc9);
2034
 
    fprintf(localVar[thrId].fp2, "\n");
2035
 
    fprintf(localVar[thrId].fp2, "\n");
2036
 
    fprintf(localVar[thrId].fp2, "No of searched nodes per depth:\n");
2037
 
    for (dd=localVar[thrId].iniDepth; dd>=0; dd--)
2038
 
      fprintf(localVar[thrId].fp2, "depth=%d  nodes=%d\n", dd, localVar[thrId].no[dd]);
2039
 
    fprintf(localVar[thrId].fp2, "\n");
2040
 
    fprintf(localVar[thrId].fp2, "Total nodes=%d\n", localVar[thrId].nodes);
2041
 
  }
2042
 
 #endif
2043
 
 
2044
 
  return value;
2045
 
}
2046
 
 
2047
 
 
2048
 
void Make(struct pos * posPoint, unsigned short int trickCards[4],
2049
 
  int depth, int trump, struct movePlyType *mply, int thrId)  {
2050
 
  int r, s, t, u, w, firstHand;
2051
 
  int suit, count, mcurr, h, q, done;
2052
 
  struct moveType mo1, mo2;
2053
 
  unsigned short aggr;
2054
 
 
2055
 
  assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
2056
 
  for (suit=0; suit<=3; suit++)
2057
 
    trickCards[suit]=0;
2058
 
 
2059
 
  firstHand=posPoint->first[depth];
2060
 
  r=mply->current;
2061
 
 
2062
 
  if (posPoint->handRelFirst==3)  {         /* This hand is last hand */
2063
 
    mo1=mply->move[r];
2064
 
    mo2=posPoint->move[depth+1];
2065
 
    if (mo1.suit==mo2.suit) {
2066
 
      if (mo1.rank>mo2.rank) {
2067
 
        posPoint->move[depth]=mo1;
2068
 
        posPoint->high[depth]=handId(firstHand, 3);
2069
 
      }
2070
 
      else {
2071
 
        posPoint->move[depth]=posPoint->move[depth+1];
2072
 
        posPoint->high[depth]=posPoint->high[depth+1];
2073
 
      }
2074
 
    }
2075
 
    else if (mo1.suit==trump) {
2076
 
      posPoint->move[depth]=mo1;
2077
 
      posPoint->high[depth]=handId(firstHand, 3);
2078
 
    }
2079
 
    else {
2080
 
      posPoint->move[depth]=posPoint->move[depth+1];
2081
 
      posPoint->high[depth]=posPoint->high[depth+1];
2082
 
    }
2083
 
 
2084
 
    /* Is the trick won by rank? */
2085
 
    suit=posPoint->move[depth].suit;
2086
 
    count=0;
2087
 
    mcurr=mply->current;
2088
 
    if (mply->move[mcurr].suit==suit)
2089
 
      count++;
2090
 
    for (h=1; h<=3; h++) {
2091
 
      mcurr=localVar[thrId].movePly[depth+h].current;
2092
 
      if (localVar[thrId].movePly[depth+h].move[mcurr].suit==suit)
2093
 
        count++;
2094
 
    }
2095
 
 
2096
 
    if (localVar[thrId].nodeTypeStore[posPoint->high[depth]]==MAXNODE)
2097
 
      posPoint->tricksMAX++;
2098
 
    posPoint->first[depth-1]=posPoint->high[depth];   /* Defines who is first
2099
 
        in the next move */
2100
 
 
2101
 
    t=handId(firstHand, 3);
2102
 
    posPoint->handRelFirst=0;      /* Hand pointed to by posPoint->first
2103
 
                                    will lead the next trick */
2104
 
 
2105
 
    done=FALSE;
2106
 
    for (s=3; s>=0; s--) {
2107
 
      q=handId(firstHand, 3-s);
2108
 
    /* Add the moves to removed ranks */
2109
 
      r=localVar[thrId].movePly[depth+s].current;
2110
 
      w=localVar[thrId].movePly[depth+s].move[r].rank;
2111
 
      u=localVar[thrId].movePly[depth+s].move[r].suit;
2112
 
      posPoint->removedRanks[u]|=bitMapRank[w];
2113
 
 
2114
 
      if (s==0)
2115
 
        posPoint->rankInSuit[t][u]&=(~bitMapRank[w]);
2116
 
 
2117
 
      if ((w==posPoint->winner[u].rank)||(w==posPoint->secondBest[u].rank)) {
2118
 
        aggr=0;
2119
 
        for (h=0; h<=3; h++)
2120
 
          aggr|=posPoint->rankInSuit[h][u];
2121
 
        posPoint->winner[u].rank=localVar[thrId].rel[aggr].absRank[1][u].rank;
2122
 
        posPoint->winner[u].hand=localVar[thrId].rel[aggr].absRank[1][u].hand;
2123
 
        posPoint->secondBest[u].rank=localVar[thrId].rel[aggr].absRank[2][u].rank;
2124
 
        posPoint->secondBest[u].hand=localVar[thrId].rel[aggr].absRank[2][u].hand;
2125
 
      }
2126
 
 
2127
 
    /* Determine win-ranked cards */
2128
 
      if ((q==posPoint->high[depth])&&(!done)) {
2129
 
        done=TRUE;
2130
 
        if (count>=2) {
2131
 
          trickCards[u]=bitMapRank[w];
2132
 
          /* Mark ranks as winning if they are part of a sequence */
2133
 
          trickCards[u]|=localVar[thrId].movePly[depth+s].move[r].sequence;
2134
 
        }
2135
 
      }
2136
 
    }
2137
 
  }
2138
 
  else if (posPoint->handRelFirst==0) {   /* Is it the 1st hand? */
2139
 
    posPoint->first[depth-1]=firstHand;   /* First hand is not changed in
2140
 
                                            next move */
2141
 
    posPoint->high[depth]=firstHand;
2142
 
    posPoint->move[depth]=mply->move[r];
2143
 
    t=firstHand;
2144
 
    posPoint->handRelFirst=1;
2145
 
    r=mply->current;
2146
 
    u=mply->move[r].suit;
2147
 
    w=mply->move[r].rank;
2148
 
    posPoint->rankInSuit[t][u]&=(~bitMapRank[w]);
2149
 
  }
2150
 
  else {
2151
 
    mo1=mply->move[r];
2152
 
    mo2=posPoint->move[depth+1];
2153
 
    r=mply->current;
2154
 
    u=mply->move[r].suit;
2155
 
    w=mply->move[r].rank;
2156
 
    if (mo1.suit==mo2.suit) {
2157
 
      if (mo1.rank>mo2.rank) {
2158
 
        posPoint->move[depth]=mo1;
2159
 
        posPoint->high[depth]=handId(firstHand, posPoint->handRelFirst);
2160
 
      }
2161
 
      else {
2162
 
        posPoint->move[depth]=posPoint->move[depth+1];
2163
 
        posPoint->high[depth]=posPoint->high[depth+1];
2164
 
      }
2165
 
    }
2166
 
    else if (mo1.suit==trump) {
2167
 
      posPoint->move[depth]=mo1;
2168
 
      posPoint->high[depth]=handId(firstHand, posPoint->handRelFirst);
2169
 
    }
2170
 
    else {
2171
 
      posPoint->move[depth]=posPoint->move[depth+1];
2172
 
      posPoint->high[depth]=posPoint->high[depth+1];
2173
 
    }
2174
 
 
2175
 
    t=handId(firstHand, posPoint->handRelFirst);
2176
 
    posPoint->handRelFirst++;               /* Current hand is stepped */
2177
 
    assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
2178
 
    posPoint->first[depth-1]=firstHand;     /* First hand is not changed in
2179
 
                                            next move */
2180
 
 
2181
 
    posPoint->rankInSuit[t][u]&=(~bitMapRank[w]);
2182
 
  }
2183
 
 
2184
 
  posPoint->length[t][u]--;
2185
 
 
2186
 
#ifdef STAT
2187
 
  localVar[thrId].no[depth]++;
2188
 
#endif
2189
 
 
2190
 
  return;
2191
 
}
2192
 
 
2193
 
 
2194
 
void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId)  {
2195
 
  int r, s, t, u, w, firstHand;
2196
 
 
2197
 
  assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
2198
 
 
2199
 
  firstHand=posPoint->first[depth];
2200
 
 
2201
 
  switch (posPoint->handRelFirst) {
2202
 
    case 3: case 2: case 1:
2203
 
     posPoint->handRelFirst--;
2204
 
     break;
2205
 
    case 0:
2206
 
     posPoint->handRelFirst=3;
2207
 
  }
2208
 
 
2209
 
  if (posPoint->handRelFirst==0) {          /* 1st hand which won the previous
2210
 
                                            trick */
2211
 
    t=firstHand;
2212
 
    r=mply->current;
2213
 
    u=mply->move[r].suit;
2214
 
    w=mply->move[r].rank;
2215
 
  }
2216
 
  else if (posPoint->handRelFirst==3)  {    /* Last hand */
2217
 
    for (s=3; s>=0; s--) {
2218
 
    /* Delete the moves from removed ranks */
2219
 
      r=localVar[thrId].movePly[depth+s].current;
2220
 
      w=localVar[thrId].movePly[depth+s].move[r].rank;
2221
 
      u=localVar[thrId].movePly[depth+s].move[r].suit;
2222
 
 
2223
 
      posPoint->removedRanks[u]&= (~bitMapRank[w]);
2224
 
 
2225
 
      if (w>posPoint->winner[u].rank) {
2226
 
        posPoint->secondBest[u].rank=posPoint->winner[u].rank;
2227
 
        posPoint->secondBest[u].hand=posPoint->winner[u].hand;
2228
 
        posPoint->winner[u].rank=w;
2229
 
        posPoint->winner[u].hand=handId(firstHand, 3-s);
2230
 
 
2231
 
      }
2232
 
      else if (w>posPoint->secondBest[u].rank) {
2233
 
        posPoint->secondBest[u].rank=w;
2234
 
        posPoint->secondBest[u].hand=handId(firstHand, 3-s);
2235
 
      }
2236
 
    }
2237
 
    t=handId(firstHand, 3);
2238
 
 
2239
 
 
2240
 
    if (localVar[thrId].nodeTypeStore[posPoint->first[depth-1]]==MAXNODE)
2241
 
        /* First hand of next trick is winner of the current trick */
2242
 
      posPoint->tricksMAX--;
2243
 
  }
2244
 
  else {
2245
 
    t=handId(firstHand, posPoint->handRelFirst);
2246
 
    r=mply->current;
2247
 
    u=mply->move[r].suit;
2248
 
    w=mply->move[r].rank;
2249
 
  }
2250
 
 
2251
 
  posPoint->rankInSuit[t][u]|=bitMapRank[w];
2252
 
 
2253
 
  posPoint->length[t][u]++;
2254
 
 
2255
 
  return;
2256
 
}
2257
 
 
2258
 
 
2259
 
 
2260
 
struct evalType Evaluate(struct pos * posPoint, int trump, int thrId)  {
2261
 
  int s, smax=0, max, k, firstHand, count;
2262
 
  struct evalType eval;
2263
 
 
2264
 
  firstHand=posPoint->first[0];
2265
 
  assert((firstHand >= 0)&&(firstHand <= 3));
2266
 
 
2267
 
  for (s=0; s<=3; s++)
2268
 
    eval.winRanks[s]=0;
2269
 
 
2270
 
  /* Who wins the last trick? */
2271
 
  if (trump!=4)  {            /* Highest trump card wins */
2272
 
    max=0;
2273
 
    count=0;
2274
 
    for (s=0; s<=3; s++) {
2275
 
      if (posPoint->rankInSuit[s][trump]!=0)
2276
 
        count++;
2277
 
      if (posPoint->rankInSuit[s][trump]>max) {
2278
 
        smax=s;
2279
 
        max=posPoint->rankInSuit[s][trump];
2280
 
      }
2281
 
    }
2282
 
 
2283
 
    if (max>0) {        /* Trumpcard wins */
2284
 
      if (count>=2)
2285
 
        eval.winRanks[trump]=max;
2286
 
 
2287
 
      if (localVar[thrId].nodeTypeStore[smax]==MAXNODE)
2288
 
        goto maxexit;
2289
 
      else
2290
 
        goto minexit;
2291
 
    }
2292
 
  }
2293
 
 
2294
 
  /* Who has the highest card in the suit played by 1st hand? */
2295
 
 
2296
 
  k=0;
2297
 
  while (k<=3)  {           /* Find the card the 1st hand played */
2298
 
    if (posPoint->rankInSuit[firstHand][k]!=0)      /* Is this the card? */
2299
 
      break;
2300
 
    k++;
2301
 
  }
2302
 
 
2303
 
  assert(k < 4);
2304
 
 
2305
 
  count=0;
2306
 
  max=0;
2307
 
  for (s=0; s<=3; s++)  {
2308
 
    if (posPoint->rankInSuit[s][k]!=0)
2309
 
      count++;
2310
 
    if (posPoint->rankInSuit[s][k]>max)  {
2311
 
      smax=s;
2312
 
      max=posPoint->rankInSuit[s][k];
2313
 
    }
2314
 
  }
2315
 
 
2316
 
  if (count>=2)
2317
 
    eval.winRanks[k]=max;
2318
 
 
2319
 
  if (localVar[thrId].nodeTypeStore[smax]==MAXNODE)
2320
 
    goto maxexit;
2321
 
  else
2322
 
    goto minexit;
2323
 
 
2324
 
  maxexit:
2325
 
  eval.tricks=posPoint->tricksMAX+1;
2326
 
  return eval;
2327
 
 
2328
 
  minexit:
2329
 
  eval.tricks=posPoint->tricksMAX;
2330
 
  return eval;
2331
 
}
2332
 
 
2333
 
 
2334
 
int QuickTricks(struct pos * posPoint, int hand,
2335
 
        int depth, int target, int trump, int *result, int thrId) {
2336
 
  int suit, sum, qtricks, commPartner, commRank=0, commSuit=-1, s, found=FALSE;
2337
 
  int opps, res;
2338
 
  int countLho, countRho, countPart, countOwn, lhoTrumpRanks, rhoTrumpRanks;
2339
 
  int cutoff, ss, rr, lowestQtricks=0, count=0/*, ruff=FALSE*/;
2340
 
 
2341
 
  int QtricksLeadHandNT(int hand, struct pos *posPoint, int cutoff, int depth,
2342
 
        int countLho, int countRho, int *lhoTrumpRanks, int *rhoTrumpRanks, int commPartner,
2343
 
        int commSuit, int countOwn, int countPart, int suit, int qtricks, int trump, int *res);
2344
 
 
2345
 
  int QtricksLeadHandTrump(int hand, struct pos *posPoint, int cutoff, int depth,
2346
 
        int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn,
2347
 
        int countPart, int suit, int qtricks, int trump, int *res);
2348
 
 
2349
 
  int QuickTricksPartnerHandTrump(int hand, struct pos *posPoint, int cutoff, int depth,
2350
 
        int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn,
2351
 
        int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId);
2352
 
 
2353
 
  int QuickTricksPartnerHandNT(int hand, struct pos *posPoint, int cutoff, int depth,
2354
 
        int countLho, int countRho, int countOwn,
2355
 
        int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId);
2356
 
 
2357
 
  *result=TRUE;
2358
 
  qtricks=0;
2359
 
  for (s=0; s<=3; s++)
2360
 
    posPoint->winRanks[depth][s]=0;
2361
 
 
2362
 
  if ((depth<=0)||(depth==localVar[thrId].iniDepth)) {
2363
 
    *result=FALSE;
2364
 
    return qtricks;
2365
 
  }
2366
 
 
2367
 
  if (localVar[thrId].nodeTypeStore[hand]==MAXNODE)
2368
 
    cutoff=target-posPoint->tricksMAX;
2369
 
  else
2370
 
    cutoff=posPoint->tricksMAX-target+(depth>>2)+2;
2371
 
 
2372
 
  commPartner=FALSE;
2373
 
  for (s=0; s<=3; s++) {
2374
 
    if ((trump!=4)&&(trump!=s)) {
2375
 
      if (posPoint->winner[s].hand==partner[hand]) {
2376
 
        /* Partner has winning card */
2377
 
        if (posPoint->rankInSuit[hand][s]!=0) {
2378
 
        /* Own hand has card in suit */
2379
 
          if (((posPoint->rankInSuit[lho[hand]][s]!=0) ||
2380
 
          /* LHO not void */
2381
 
          (posPoint->rankInSuit[lho[hand]][trump]==0))
2382
 
          /* LHO has no trump */
2383
 
          && ((posPoint->rankInSuit[rho[hand]][s]!=0) ||
2384
 
          /* RHO not void */
2385
 
          (posPoint->rankInSuit[rho[hand]][trump]==0))) {
2386
 
          /* RHO has no trump */
2387
 
            commPartner=TRUE;
2388
 
            commSuit=s;
2389
 
            commRank=posPoint->winner[s].rank;
2390
 
            break;
2391
 
          }
2392
 
        }
2393
 
      }
2394
 
      else if (posPoint->secondBest[s].hand==partner[hand]) {
2395
 
        if ((posPoint->winner[s].hand==hand)&&
2396
 
          (posPoint->length[hand][s]>=2)&&(posPoint->length[partner[hand]][s]>=2)) {
2397
 
          if (((posPoint->rankInSuit[lho[hand]][s]!=0) ||
2398
 
            (posPoint->rankInSuit[lho[hand]][trump]==0))
2399
 
            && ((posPoint->rankInSuit[rho[hand]][s]!=0) ||
2400
 
            (posPoint->rankInSuit[rho[hand]][trump]==0))) {
2401
 
            commPartner=TRUE;
2402
 
            commSuit=s;
2403
 
            commRank=posPoint->secondBest[s].rank;
2404
 
            break;
2405
 
          }
2406
 
        }
2407
 
      }
2408
 
    }
2409
 
    else if (trump==4) {
2410
 
      if (posPoint->winner[s].hand==partner[hand]) {
2411
 
        /* Partner has winning card */
2412
 
        if (posPoint->rankInSuit[hand][s]!=0) {
2413
 
        /* Own hand has card in suit */
2414
 
          commPartner=TRUE;
2415
 
          commSuit=s;
2416
 
          commRank=posPoint->winner[s].rank;
2417
 
          break;
2418
 
        }
2419
 
      }
2420
 
      else if (posPoint->secondBest[s].hand==partner[hand]) {
2421
 
        if ((posPoint->winner[s].hand==hand)&&
2422
 
          (posPoint->length[hand][s]>=2)&&(posPoint->length[partner[hand]][s]>=2)) {
2423
 
          commPartner=TRUE;
2424
 
          commSuit=s;
2425
 
          commRank=posPoint->secondBest[s].rank;
2426
 
          break;
2427
 
        }
2428
 
      }
2429
 
    }
2430
 
  }
2431
 
 
2432
 
  if ((trump!=4) && (!commPartner) &&
2433
 
          (posPoint->rankInSuit[hand][trump]!=0) &&
2434
 
          (posPoint->winner[trump].hand==partner[hand])) {
2435
 
    commPartner=TRUE;
2436
 
    commSuit=trump;
2437
 
    commRank=posPoint->winner[trump].rank;
2438
 
  }
2439
 
 
2440
 
 
2441
 
  if (trump!=4) {
2442
 
    suit=trump;
2443
 
    lhoTrumpRanks=posPoint->length[lho[hand]][trump];
2444
 
    rhoTrumpRanks=posPoint->length[rho[hand]][trump];
2445
 
  }
2446
 
  else
2447
 
    suit=0;
2448
 
 
2449
 
  do {
2450
 
    countOwn=posPoint->length[hand][suit];
2451
 
    countLho=posPoint->length[lho[hand]][suit];
2452
 
    countRho=posPoint->length[rho[hand]][suit];
2453
 
    countPart=posPoint->length[partner[hand]][suit];
2454
 
    opps=countLho | countRho;
2455
 
 
2456
 
    if (!opps && (countPart==0)) {
2457
 
      if (countOwn==0) {
2458
 
        /* Continue with next suit. */
2459
 
        if ((trump!=4)&&(trump!=suit)) {
2460
 
          suit++;
2461
 
          if ((trump!=4) && (suit==trump))
2462
 
            suit++;
2463
 
        }
2464
 
        else {
2465
 
          if ((trump!=4) && (trump==suit)) {
2466
 
            if (trump==0)
2467
 
              suit=1;
2468
 
            else
2469
 
              suit=0;
2470
 
          }
2471
 
          else
2472
 
            suit++;
2473
 
        }
2474
 
        continue;
2475
 
      }
2476
 
 
2477
 
      /* Long tricks when only leading hand have cards in the suit. */
2478
 
      if ((trump!=4) && (trump!=suit)) {
2479
 
        if ((lhoTrumpRanks==0) && (rhoTrumpRanks==0)) {
2480
 
          qtricks+=countOwn;
2481
 
          if (qtricks>=cutoff)
2482
 
            return qtricks;
2483
 
          suit++;
2484
 
          if ((trump!=4) && (suit==trump))
2485
 
            suit++;
2486
 
          continue;
2487
 
        }
2488
 
        else {
2489
 
          suit++;
2490
 
          if ((trump!=4) && (suit==trump))
2491
 
            suit++;
2492
 
          continue;
2493
 
        }
2494
 
      }
2495
 
      else {
2496
 
        qtricks+=countOwn;
2497
 
        if (qtricks>=cutoff)
2498
 
          return qtricks;
2499
 
 
2500
 
        if ((trump!=4) && (suit==trump)) {
2501
 
          if (trump==0)
2502
 
            suit=1;
2503
 
          else
2504
 
            suit=0;
2505
 
        }
2506
 
        else {
2507
 
          suit++;
2508
 
          if ((trump!=4) && (suit==trump))
2509
 
            suit++;
2510
 
        }
2511
 
        continue;
2512
 
      }
2513
 
    }
2514
 
    else {
2515
 
      if (!opps && (trump!=4) && (suit==trump)) {
2516
 
        /* The partner but not the opponents have cards in the trump suit. */
2517
 
        sum=Max(countOwn, countPart);
2518
 
        for (s=0; s<=3; s++) {
2519
 
          if ((sum>0)&&(s!=trump)&&(countOwn>=countPart)&&(posPoint->length[hand][s]>0)&&
2520
 
            (posPoint->length[partner[hand]][s]==0)) {
2521
 
            sum++;
2522
 
            break;
2523
 
          }
2524
 
        }
2525
 
        /* If the additional trick by ruffing causes a cutoff. (qtricks not incremented.) */
2526
 
        if (sum>=cutoff)
2527
 
          return sum;
2528
 
      }
2529
 
      else if (!opps) {
2530
 
        /* The partner but not the opponents have cards in the suit. */
2531
 
        sum=Min(countOwn,countPart);
2532
 
        if (trump==4) {
2533
 
          if (sum>=cutoff)
2534
 
            return sum;
2535
 
        }
2536
 
        else if ((suit!=trump)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
2537
 
          if (sum>=cutoff)
2538
 
            return sum;
2539
 
        }
2540
 
      }
2541
 
 
2542
 
      if (commPartner) {
2543
 
        if (!opps && (countOwn==0)) {
2544
 
          if ((trump!=4) && (trump!=suit)) {
2545
 
            if ((lhoTrumpRanks==0) && (rhoTrumpRanks==0)) {
2546
 
              qtricks+=countPart;
2547
 
              posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
2548
 
              if (qtricks>=cutoff)
2549
 
                return qtricks;
2550
 
              suit++;
2551
 
              if ((trump!=4) && (suit==trump))
2552
 
                suit++;
2553
 
              continue;
2554
 
            }
2555
 
            else {
2556
 
              suit++;
2557
 
              if ((trump!=4) && (suit==trump))
2558
 
                suit++;
2559
 
              continue;
2560
 
            }
2561
 
          }
2562
 
          else {
2563
 
            qtricks+=countPart;
2564
 
            posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
2565
 
                if (qtricks>=cutoff)
2566
 
              return qtricks;
2567
 
            if ((trump!=4) && (suit==trump)) {
2568
 
              if (trump==0)
2569
 
                suit=1;
2570
 
              else
2571
 
                suit=0;
2572
 
            }
2573
 
            else {
2574
 
              suit++;
2575
 
              if ((trump!=4) && (suit==trump))
2576
 
                suit++;
2577
 
            }
2578
 
            continue;
2579
 
          }
2580
 
        }
2581
 
        else {
2582
 
          if (!opps && (trump!=4) && (suit==trump)) {
2583
 
            sum=Max(countOwn, countPart);
2584
 
            for (s=0; s<=3; s++) {
2585
 
              if ((sum>0)&&(s!=trump)&&(countOwn<=countPart)&&(posPoint->length[partner[hand]][s]>0)&&
2586
 
                 (posPoint->length[hand][s]==0)) {
2587
 
                sum++;
2588
 
                break;
2589
 
              }
2590
 
            }
2591
 
            if (sum>=cutoff) {
2592
 
              posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
2593
 
              return sum;
2594
 
            }
2595
 
          }
2596
 
          else if (!opps) {
2597
 
            sum=Min(countOwn,countPart);
2598
 
            if (trump==4) {
2599
 
              if (sum>=cutoff)
2600
 
                return sum;
2601
 
            }
2602
 
            else if ((suit!=trump)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
2603
 
              if (sum>=cutoff)
2604
 
                return sum;
2605
 
            }
2606
 
          }
2607
 
        }
2608
 
      }
2609
 
    }
2610
 
 
2611
 
    if (posPoint->winner[suit].rank==0) {
2612
 
      if ((trump!=4) && (suit==trump)) {
2613
 
        if (trump==0)
2614
 
          suit=1;
2615
 
        else
2616
 
          suit=0;
2617
 
      }
2618
 
      else {
2619
 
        suit++;
2620
 
        if ((trump!=4) && (suit==trump))
2621
 
          suit++;
2622
 
      }
2623
 
      continue;
2624
 
    }
2625
 
 
2626
 
    if (posPoint->winner[suit].hand==hand) {
2627
 
      if ((trump!=4)&&(trump!=suit)) {
2628
 
        qtricks=QtricksLeadHandTrump(hand, posPoint, cutoff, depth,
2629
 
               countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, countOwn,
2630
 
               countPart, suit, qtricks, trump, &res);
2631
 
        if (res==1)
2632
 
          return qtricks;
2633
 
        else if (res==2) {
2634
 
          suit++;
2635
 
          if ((trump!=4) && (suit==trump))
2636
 
            suit++;
2637
 
          continue;
2638
 
        }
2639
 
      }
2640
 
      else {
2641
 
        qtricks=QtricksLeadHandNT(hand, posPoint, cutoff, depth,
2642
 
          countLho, countRho, &lhoTrumpRanks, &rhoTrumpRanks,
2643
 
          commPartner, commSuit, countOwn,
2644
 
          countPart, suit, qtricks, trump, &res);
2645
 
        if (res==1)
2646
 
          return qtricks;
2647
 
        else if (res==2) {
2648
 
          if ((trump!=4) && (trump==suit)) {
2649
 
            if (trump==0)
2650
 
              suit=1;
2651
 
            else
2652
 
              suit=0;
2653
 
          }
2654
 
          else
2655
 
            suit++;
2656
 
          continue;
2657
 
        }
2658
 
      }
2659
 
    }
2660
 
 
2661
 
    /* It was not possible to take a quick trick by own winning card in
2662
 
    the suit */
2663
 
    else {
2664
 
    /* Partner winning card? */
2665
 
      if ((posPoint->winner[suit].hand==partner[hand])&&(1/*countPart>0*/)) {
2666
 
        /* Winner found at partner*/
2667
 
        if (commPartner) {
2668
 
        /* There is communication with the partner */
2669
 
          if ((trump!=4)&&(trump!=suit)) {
2670
 
            qtricks=QuickTricksPartnerHandTrump(hand, posPoint, cutoff, depth,
2671
 
              countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, countOwn,
2672
 
              countPart, suit, qtricks, commSuit, commRank, trump, &res, thrId);
2673
 
            if (res==1)
2674
 
              return qtricks;
2675
 
            else if (res==2) {
2676
 
              suit++;
2677
 
              if ((trump!=4) && (suit==trump))
2678
 
                suit++;
2679
 
              continue;
2680
 
            }
2681
 
          }
2682
 
          else {
2683
 
            qtricks=QuickTricksPartnerHandNT(hand, posPoint, cutoff, depth,
2684
 
              countLho, countRho, countOwn,
2685
 
              countPart, suit, qtricks, commSuit, commRank, trump, &res, thrId);
2686
 
            if (res==1)
2687
 
              return qtricks;
2688
 
            else if (res==2) {
2689
 
              if ((trump!=4) && (trump==suit)) {
2690
 
                if (trump==0)
2691
 
                  suit=1;
2692
 
                else
2693
 
                  suit=0;
2694
 
              }
2695
 
              else
2696
 
                suit++;
2697
 
              continue;
2698
 
            }
2699
 
          }
2700
 
        }
2701
 
      }
2702
 
    }
2703
 
    if ((trump!=4) &&(suit!=trump)&&
2704
 
        (countOwn>0)&&(lowestQtricks==0)&&
2705
 
        ((qtricks==0)||((posPoint->winner[suit].hand!=hand)&&
2706
 
        (posPoint->winner[suit].hand!=partner[hand])&&
2707
 
        (posPoint->winner[trump].hand!=hand)&&
2708
 
        (posPoint->winner[trump].hand!=partner[hand])))) {
2709
 
      if ((countPart==0)&&(posPoint->length[partner[hand]][trump]>0)) {
2710
 
        if (((countRho>0)||(posPoint->length[rho[hand]][trump]==0))&&
2711
 
          ((countLho>0)||(posPoint->length[lho[hand]][trump]==0))) {
2712
 
          lowestQtricks=1;
2713
 
          if (1>=cutoff)
2714
 
            return 1;
2715
 
          suit++;
2716
 
          if ((trump!=4) && (suit==trump))
2717
 
            suit++;
2718
 
          continue;
2719
 
        }
2720
 
        else if ((countRho==0)&&(countLho==0)) {
2721
 
          if ((posPoint->rankInSuit[lho[hand]][trump] |
2722
 
             posPoint->rankInSuit[rho[hand]][trump]) <
2723
 
             posPoint->rankInSuit[partner[hand]][trump]) {
2724
 
            lowestQtricks=1;
2725
 
 
2726
 
            rr=highestRank[posPoint->rankInSuit[partner[hand]][trump]];
2727
 
            if (rr!=0) {
2728
 
              posPoint->winRanks[depth][trump]|=bitMapRank[rr];
2729
 
              if (1>=cutoff)
2730
 
                return 1;
2731
 
            }
2732
 
          }
2733
 
          suit++;
2734
 
          if ((trump!=4) && (suit==trump))
2735
 
            suit++;
2736
 
          continue;
2737
 
        }
2738
 
        else if (countLho==0) {
2739
 
          if (posPoint->rankInSuit[lho[hand]][trump] <
2740
 
                posPoint->rankInSuit[partner[hand]][trump]) {
2741
 
            lowestQtricks=1;
2742
 
            for (rr=14; rr>=2; rr--) {
2743
 
              if ((posPoint->rankInSuit[partner[hand]][trump] &
2744
 
                bitMapRank[rr])!=0) {
2745
 
                posPoint->winRanks[depth][trump]|=bitMapRank[rr];
2746
 
                break;
2747
 
              }
2748
 
            }
2749
 
            if (1>=cutoff)
2750
 
              return 1;
2751
 
          }
2752
 
          suit++;
2753
 
          if ((trump!=4) && (suit==trump))
2754
 
            suit++;
2755
 
          continue;
2756
 
        }
2757
 
        else if (countRho==0) {
2758
 
          if (posPoint->rankInSuit[rho[hand]][trump] <
2759
 
            posPoint->rankInSuit[partner[hand]][trump]) {
2760
 
            lowestQtricks=1;
2761
 
            for (rr=14; rr>=2; rr--) {
2762
 
              if ((posPoint->rankInSuit[partner[hand]][trump] &
2763
 
                bitMapRank[rr])!=0) {
2764
 
                posPoint->winRanks[depth][trump]|=bitMapRank[rr];
2765
 
                break;
2766
 
              }
2767
 
            }
2768
 
            if (1>=cutoff)
2769
 
              return 1;
2770
 
          }
2771
 
          suit++;
2772
 
          if ((trump!=4) && (suit==trump))
2773
 
            suit++;
2774
 
          continue;
2775
 
        }
2776
 
      }
2777
 
    }
2778
 
    if (qtricks>=cutoff)
2779
 
      return qtricks;
2780
 
    if ((trump!=4) && (suit==trump)) {
2781
 
      if (trump==0)
2782
 
        suit=1;
2783
 
      else
2784
 
        suit=0;
2785
 
    }
2786
 
    else {
2787
 
      suit++;
2788
 
      if ((trump!=4) && (suit==trump))
2789
 
        suit++;
2790
 
    }
2791
 
  }
2792
 
  while (suit<=3);
2793
 
 
2794
 
  if (qtricks==0) {
2795
 
    if ((trump==4)||(posPoint->winner[trump].hand==-1)) {
2796
 
      for (ss=0; ss<=3; ss++) {
2797
 
        if (posPoint->winner[ss].hand==-1)
2798
 
          continue;
2799
 
        if (posPoint->length[hand][ss]>0) {
2800
 
          posPoint->winRanks[depth][ss]=
2801
 
            bitMapRank[posPoint->winner[ss].rank];
2802
 
        }
2803
 
      }
2804
 
      if (localVar[thrId].nodeTypeStore[hand]!=MAXNODE)
2805
 
        cutoff=target-posPoint->tricksMAX;
2806
 
      else
2807
 
        cutoff=posPoint->tricksMAX-target+(depth>>2)+2;
2808
 
 
2809
 
      if (1>=cutoff)
2810
 
        return 0;
2811
 
    }
2812
 
  }
2813
 
 
2814
 
 
2815
 
  *result=FALSE;
2816
 
  return qtricks;
2817
 
}
2818
 
 
2819
 
 
2820
 
int QtricksLeadHandTrump(int hand, struct pos *posPoint, int cutoff, int depth,
2821
 
      int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn,
2822
 
      int countPart, int suit, int qtricks, int trump, int *res) {
2823
 
        /* res=0                Continue with same suit.
2824
 
           res=1                Cutoff.
2825
 
           res=2                Continue with next suit. */
2826
 
 
2827
 
  int qt;
2828
 
 
2829
 
  *res=1;
2830
 
  qt=qtricks;
2831
 
  if (((countLho!=0) || (lhoTrumpRanks==0)) && ((countRho!=0) || (rhoTrumpRanks==0))) {
2832
 
    posPoint->winRanks[depth][suit]|=
2833
 
            bitMapRank[posPoint->winner[suit].rank];
2834
 
    qt++;
2835
 
    if (qt>=cutoff)
2836
 
      return qt;
2837
 
 
2838
 
    if ((countLho<=1)&&(countRho<=1)&&(countPart<=1)&&
2839
 
       (lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
2840
 
      qt+=countOwn-1;
2841
 
      if (qt>=cutoff)
2842
 
        return qt;
2843
 
      *res=2;
2844
 
      return qt;
2845
 
    }
2846
 
  }
2847
 
 
2848
 
  if (posPoint->secondBest[suit].hand==hand) {
2849
 
    if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
2850
 
      posPoint->winRanks[depth][suit]|=
2851
 
           bitMapRank[posPoint->secondBest[suit].rank];
2852
 
      qt++;
2853
 
      if (qt>=cutoff)
2854
 
        return qt;
2855
 
      if ((countLho<=2)&&(countRho<=2)&&(countPart<=2)) {
2856
 
        qt+=countOwn-2;
2857
 
        if (qt>=cutoff)
2858
 
          return qt;
2859
 
        *res=2;
2860
 
        return qt;
2861
 
      }
2862
 
      /*else {
2863
 
        aggr=0;
2864
 
        for (k=0; k<=3; k++)
2865
 
          aggr|=posPoint->rankInSuit[k][suit];
2866
 
        if (rel[aggr].absRank[3][suit].hand==hand) {
2867
 
          qt++;
2868
 
          posPoint->winRanks[depth][suit]|=
2869
 
          bitMapRank[rel[aggr].absRank[3][suit].rank];
2870
 
          if (qt>=cutoff)
2871
 
            return qt;
2872
 
          if ((countLho<=3)&&(countRho<=3)&&(countPart<=3)) {
2873
 
            qt+=countOwn-3;
2874
 
            if (qt>=cutoff)
2875
 
              return qt;
2876
 
          }
2877
 
          *res=2;
2878
 
          return qt;
2879
 
        }
2880
 
      }*/
2881
 
    }
2882
 
  }
2883
 
  else if ((posPoint->secondBest[suit].hand==partner[hand])
2884
 
    &&(countOwn>1)&&(countPart>1)) {
2885
 
    /* Second best at partner and suit length of own
2886
 
           hand and partner > 1 */
2887
 
    if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
2888
 
      posPoint->winRanks[depth][suit]|=
2889
 
           bitMapRank[posPoint->secondBest[suit].rank];
2890
 
      qt++;
2891
 
      if (qt>=cutoff)
2892
 
        return qt;
2893
 
      if ((countLho<=2)&&(countRho<=2)&&((countPart<=2)||(countOwn<=2))) {
2894
 
        qt+=Max(countOwn-2, countPart-2);
2895
 
        if (qt>=cutoff)
2896
 
          return qt;
2897
 
        *res=2;
2898
 
        return qt;
2899
 
      }
2900
 
    }
2901
 
  }
2902
 
  *res=0;
2903
 
  return qt;
2904
 
}
2905
 
 
2906
 
int QtricksLeadHandNT(int hand, struct pos *posPoint, int cutoff, int depth,
2907
 
        int countLho, int countRho, int *lhoTrumpRanks, int *rhoTrumpRanks,
2908
 
        int commPartner, int commSuit, int countOwn,
2909
 
        int countPart, int suit, int qtricks, int trump, int *res) {
2910
 
        /* res=0                Continue with same suit.
2911
 
           res=1                Cutoff.
2912
 
           res=2                Continue with next suit. */
2913
 
 
2914
 
  int qt;
2915
 
 
2916
 
  *res=1;
2917
 
  qt=qtricks;
2918
 
  posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank];
2919
 
  qt++;
2920
 
  if (qt>=cutoff)
2921
 
    return qt;
2922
 
  if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) {
2923
 
  /*if (trump==suit) {*/
2924
 
    (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1);
2925
 
    (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1);
2926
 
  }
2927
 
 
2928
 
  if ((countLho<=1)&&(countRho<=1)&&(countPart<=1)) {
2929
 
    qt+=countOwn-1;
2930
 
    if (qt>=cutoff)
2931
 
      return qt;
2932
 
    *res=2;
2933
 
    return qt;
2934
 
  }
2935
 
 
2936
 
  if (posPoint->secondBest[suit].hand==hand) {
2937
 
    posPoint->winRanks[depth][suit]|=
2938
 
      bitMapRank[posPoint->secondBest[suit].rank];
2939
 
    qt++;
2940
 
    if (qt>=cutoff)
2941
 
      return qt;
2942
 
    if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) {
2943
 
        /*if (trump==suit) {*/
2944
 
      (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1);
2945
 
      (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1);
2946
 
    }
2947
 
    if ((countLho<=2)&&(countRho<=2)&&(countPart<=2)) {
2948
 
      qt+=countOwn-2;
2949
 
      if (qt>=cutoff)
2950
 
        return qt;
2951
 
      *res=2;
2952
 
      return qt;
2953
 
    }
2954
 
    /*else {
2955
 
      aggr=0;
2956
 
      for (k=0; k<=3; k++)
2957
 
        aggr|=posPoint->rankInSuit[k][suit];
2958
 
      if (rel[aggr].absRank[3][suit].hand==hand) {
2959
 
        qt++;
2960
 
        posPoint->winRanks[depth][suit]|=
2961
 
           bitMapRank[rel[aggr].absRank[3][suit].rank];
2962
 
        if (qt>=cutoff)
2963
 
          return qt;
2964
 
        if ((countLho<=3)&&(countRho<=3)&&(countPart<=3)) {
2965
 
          qt+=countOwn-3;
2966
 
          if (qt>=cutoff)
2967
 
            return qt;
2968
 
        }
2969
 
        *res=2;
2970
 
        return qt;
2971
 
      }
2972
 
    }*/
2973
 
  }
2974
 
  else if ((posPoint->secondBest[suit].hand==partner[hand])
2975
 
      &&(countOwn>1)&&(countPart>1)) {
2976
 
     /* Second best at partner and suit length of own
2977
 
            hand and partner > 1 */
2978
 
    posPoint->winRanks[depth][suit]|=
2979
 
        bitMapRank[posPoint->secondBest[suit].rank];
2980
 
    qt++;
2981
 
    if (qt>=cutoff)
2982
 
      return qt;
2983
 
        if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) {
2984
 
    /*if (trump==suit) {*/
2985
 
      (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1);
2986
 
      (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1);
2987
 
    }
2988
 
    if ((countLho<=2)&&(countRho<=2)&&((countPart<=2)||(countOwn<=2))) {
2989
 
      qt+=Max(countOwn-2,countPart-2);
2990
 
      if (qt>=cutoff)
2991
 
        return qt;
2992
 
      *res=2;
2993
 
      return qt;
2994
 
    }
2995
 
    /*else if (countPart>2) {
2996
 
      aggr=0;
2997
 
      for (k=0; k<=3; k++)
2998
 
        aggr|=posPoint->rankInSuit[k][suit];
2999
 
      if (rel[aggr].absRank[3][suit].hand==hand) {
3000
 
        qt++;
3001
 
        posPoint->winRanks[depth][suit]|=
3002
 
           bitMapRank[rel[aggr].absRank[3][suit].rank];
3003
 
        if (qt>=cutoff)
3004
 
          return qt;
3005
 
        *res=2;
3006
 
        return qt;
3007
 
      }
3008
 
    }*/
3009
 
  }
3010
 
 
3011
 
  *res=0;
3012
 
  return qt;
3013
 
}
3014
 
 
3015
 
 
3016
 
int QuickTricksPartnerHandTrump(int hand, struct pos *posPoint, int cutoff, int depth,
3017
 
        int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn,
3018
 
        int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId) {
3019
 
        /* res=0                Continue with same suit.
3020
 
           res=1                Cutoff.
3021
 
           res=2                Continue with next suit. */
3022
 
 
3023
 
  int qt, k;
3024
 
  unsigned short ranks;
3025
 
 
3026
 
  *res=1;
3027
 
  qt=qtricks;
3028
 
  if (((countLho!=0) || (lhoTrumpRanks==0)) && ((countRho!=0) || (rhoTrumpRanks==0))) {
3029
 
    posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank];
3030
 
    posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
3031
 
    qt++;   /* A trick can be taken */
3032
 
    if (qt>=cutoff)
3033
 
      return qt;
3034
 
    if ((countLho<=1)&&(countRho<=1)&&(countOwn<=1)&&(lhoTrumpRanks==0)&&
3035
 
       (rhoTrumpRanks==0)) {
3036
 
      qt+=countPart-1;
3037
 
      if (qt>=cutoff)
3038
 
        return qt;
3039
 
      *res=2;
3040
 
      return qt;
3041
 
    }
3042
 
  }
3043
 
 
3044
 
  if (posPoint->secondBest[suit].hand==partner[hand]) {
3045
 
    /* Second best found in partners hand */
3046
 
    if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
3047
 
        /* Opponents have no trump */
3048
 
      posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank];
3049
 
      posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
3050
 
      qt++;
3051
 
      if (qt>=cutoff)
3052
 
        return qt;
3053
 
      if ((countLho<=2)&&(countRho<=2)&&(countOwn<=2)) {
3054
 
        qt+=countPart-2;
3055
 
        if (qt>=cutoff)
3056
 
          return qt;
3057
 
        *res=2;
3058
 
        return qt;
3059
 
      }
3060
 
    }
3061
 
  }
3062
 
  else if ((posPoint->secondBest[suit].hand==hand)&&(countPart>1)&&(countOwn>1)) {
3063
 
     /* Second best found in own hand and suit lengths of own hand and partner > 1*/
3064
 
    if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
3065
 
      /* Opponents have no trump */
3066
 
      posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank];
3067
 
      posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
3068
 
      qt++;
3069
 
      if (qt>=cutoff)
3070
 
        return qt;
3071
 
      if ((countLho<=2)&&(countRho<=2)&&((countOwn<=2)||(countPart<=2))) {
3072
 
        qt+=Max(countPart-2,countOwn-2);
3073
 
        if (qt>=cutoff)
3074
 
          return qt;
3075
 
        *res=2;
3076
 
        return qt;
3077
 
      }
3078
 
    }
3079
 
  }
3080
 
  else if ((suit==commSuit)&&(posPoint->secondBest[suit].hand==lho[hand])&&
3081
 
          ((countLho>=2)||(lhoTrumpRanks==0))&&((countRho>=2)||(rhoTrumpRanks==0))) {
3082
 
    ranks=0;
3083
 
    for (k=0; k<=3; k++)
3084
 
      ranks|=posPoint->rankInSuit[k][suit];
3085
 
    if (localVar[thrId].rel[ranks].absRank[3][suit].hand==partner[hand]) {
3086
 
          posPoint->winRanks[depth][suit]|=bitMapRank[localVar[thrId].rel[ranks].absRank[3][suit].rank];
3087
 
      posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
3088
 
      qt++;
3089
 
      if (qt>=cutoff)
3090
 
        return qt;
3091
 
      if ((countOwn<=2)&&(countLho<=2)&&(countRho<=2)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
3092
 
        qt+=countPart-2;
3093
 
        if (qt>=cutoff)
3094
 
          return qt;
3095
 
      }
3096
 
    }
3097
 
  }
3098
 
  *res=0;
3099
 
  return qt;
3100
 
}
3101
 
 
3102
 
 
3103
 
int QuickTricksPartnerHandNT(int hand, struct pos *posPoint, int cutoff, int depth,
3104
 
        int countLho, int countRho, int countOwn,
3105
 
        int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId) {
3106
 
 
3107
 
  int qt, k/*, found, rr*/;
3108
 
  unsigned short ranks;
3109
 
 
3110
 
  *res=1;
3111
 
  qt=qtricks;
3112
 
 
3113
 
  posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank];
3114
 
  posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
3115
 
  qt++;
3116
 
  if (qt>=cutoff)
3117
 
    return qt;
3118
 
  if ((countLho<=1)&&(countRho<=1)&&(countOwn<=1)) {
3119
 
    qt+=countPart-1;
3120
 
    if (qt>=cutoff)
3121
 
      return qt;
3122
 
   *res=2;
3123
 
    return qt;
3124
 
  }
3125
 
 
3126
 
  if ((posPoint->secondBest[suit].hand==partner[hand])&&(1/*countPart>0*/)) {
3127
 
       /* Second best found in partners hand */
3128
 
    posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank];
3129
 
    qt++;
3130
 
    if (qt>=cutoff)
3131
 
      return qt;
3132
 
    if ((countLho<=2)&&(countRho<=2)&&(countOwn<=2)) {
3133
 
      qt+=countPart-2;
3134
 
      if (qt>=cutoff)
3135
 
        return qt;
3136
 
      *res=2;
3137
 
      return qt;
3138
 
    }
3139
 
  }
3140
 
  else if ((posPoint->secondBest[suit].hand==hand)
3141
 
                  &&(countPart>1)&&(countOwn>1)) {
3142
 
        /* Second best found in own hand and own and
3143
 
                   partner's suit length > 1 */
3144
 
    posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank];
3145
 
    qt++;
3146
 
    if (qt>=cutoff)
3147
 
      return qt;
3148
 
    if ((countLho<=2)&&(countRho<=2)&&((countOwn<=2)||(countPart<=2))) {
3149
 
      qt+=Max(countPart-2,countOwn-2);
3150
 
      if (qt>=cutoff)
3151
 
        return qt;
3152
 
      *res=2;
3153
 
      return qt;
3154
 
    }
3155
 
  }
3156
 
  else if ((suit==commSuit)&&(posPoint->secondBest[suit].hand==lho[hand])) {
3157
 
    ranks=0;
3158
 
    for (k=0; k<=3; k++)
3159
 
      ranks=ranks | posPoint->rankInSuit[k][suit];
3160
 
    if (localVar[thrId].rel[ranks].absRank[3][suit].hand==partner[hand]) {
3161
 
      posPoint->winRanks[depth][suit]|=bitMapRank[localVar[thrId].rel[ranks].absRank[3][suit].rank];
3162
 
      qt++;
3163
 
      if (qt>=cutoff)
3164
 
        return qt;
3165
 
      if ((countOwn<=2)&&(countLho<=2)&&(countRho<=2)) {
3166
 
        qtricks+=countPart-2;
3167
 
        if (qt>=cutoff)
3168
 
          return qt;
3169
 
      }
3170
 
    }
3171
 
  }
3172
 
  *res=0;
3173
 
  return qt;
3174
 
}
3175
 
 
3176
 
 
3177
 
int LaterTricksMIN(struct pos *posPoint, int hand, int depth, int target,
3178
 
        int trump, int thrId) {
3179
 
  int hh, ss, k, h, sum=0;
3180
 
  unsigned short aggr;
3181
 
 
3182
 
  if ((trump==4)||(posPoint->winner[trump].rank==0)) {
3183
 
    for (ss=0; ss<=3; ss++) {
3184
 
      hh=posPoint->winner[ss].hand;
3185
 
      if (hh!=-1) {
3186
 
        if (localVar[thrId].nodeTypeStore[hh]==MAXNODE)
3187
 
          sum+=Max(posPoint->length[hh][ss], posPoint->length[partner[hh]][ss]);
3188
 
      }
3189
 
    }
3190
 
    if ((posPoint->tricksMAX+sum<target)&&
3191
 
      (sum>0)&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3192
 
      if ((posPoint->tricksMAX+(depth>>2)<target)) {
3193
 
        for (ss=0; ss<=3; ss++) {
3194
 
          if (posPoint->winner[ss].hand==-1)
3195
 
            posPoint->winRanks[depth][ss]=0;
3196
 
          else if (localVar[thrId].nodeTypeStore[posPoint->winner[ss].hand]==MINNODE) {
3197
 
            if ((posPoint->rankInSuit[partner[posPoint->winner[ss].hand]][ss]==0)&&
3198
 
                (posPoint->rankInSuit[lho[posPoint->winner[ss].hand]][ss]==0)&&
3199
 
                (posPoint->rankInSuit[rho[posPoint->winner[ss].hand]][ss]==0))
3200
 
              posPoint->winRanks[depth][ss]=0;
3201
 
            else
3202
 
              posPoint->winRanks[depth][ss]=bitMapRank[posPoint->winner[ss].rank];
3203
 
          }
3204
 
          else
3205
 
            posPoint->winRanks[depth][ss]=0;
3206
 
        }
3207
 
        return FALSE;
3208
 
      }
3209
 
    }
3210
 
  }
3211
 
  else if ((trump!=4) && (posPoint->winner[trump].rank!=0) &&
3212
 
    (localVar[thrId].nodeTypeStore[posPoint->winner[trump].hand]==MINNODE)) {
3213
 
    if ((posPoint->length[hand][trump]==0)&&
3214
 
      (posPoint->length[partner[hand]][trump]==0)) {
3215
 
      if (((posPoint->tricksMAX+(depth>>2)+1-
3216
 
          Max(posPoint->length[lho[hand]][trump],
3217
 
          posPoint->length[rho[hand]][trump]))<target)
3218
 
          &&(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3219
 
        for (ss=0; ss<=3; ss++)
3220
 
          posPoint->winRanks[depth][ss]=0;
3221
 
        return FALSE;
3222
 
      }
3223
 
    }
3224
 
    else if (((posPoint->tricksMAX+(depth>>2))<target)&&
3225
 
      (depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3226
 
      for (ss=0; ss<=3; ss++)
3227
 
        posPoint->winRanks[depth][ss]=0;
3228
 
      posPoint->winRanks[depth][trump]=
3229
 
          bitMapRank[posPoint->winner[trump].rank];
3230
 
      return FALSE;
3231
 
    }
3232
 
    else {
3233
 
      hh=posPoint->secondBest[trump].hand;
3234
 
      if (hh!=-1) {
3235
 
        if ((localVar[thrId].nodeTypeStore[hh]==MINNODE)&&(posPoint->secondBest[trump].rank!=0))  {
3236
 
          if (((posPoint->length[hh][trump]>1) ||
3237
 
            (posPoint->length[partner[hh]][trump]>1))&&
3238
 
            ((posPoint->tricksMAX+(depth>>2)-1)<target)&&(depth>0)
3239
 
             &&(depth!=localVar[thrId].iniDepth)) {
3240
 
            for (ss=0; ss<=3; ss++)
3241
 
              posPoint->winRanks[depth][ss]=0;
3242
 
            posPoint->winRanks[depth][trump]=
3243
 
              bitMapRank[posPoint->secondBest[trump].rank] ;
3244
 
                 return FALSE;
3245
 
          }
3246
 
        }
3247
 
      }
3248
 
    }
3249
 
  }
3250
 
  else if (trump!=4) {
3251
 
    hh=posPoint->secondBest[trump].hand;
3252
 
    if (hh!=-1) {
3253
 
      if ((localVar[thrId].nodeTypeStore[hh]==MINNODE)&&
3254
 
        (posPoint->length[hh][trump]>1)) {
3255
 
        if (posPoint->winner[trump].hand==rho[hh]) {
3256
 
          if (((posPoint->tricksMAX+(depth>>2))<target)&&
3257
 
            (depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3258
 
            for (ss=0; ss<=3; ss++)
3259
 
              posPoint->winRanks[depth][ss]=0;
3260
 
                posPoint->winRanks[depth][trump]=
3261
 
              bitMapRank[posPoint->secondBest[trump].rank];
3262
 
            return FALSE;
3263
 
          }
3264
 
        }
3265
 
        else {
3266
 
          aggr=0;
3267
 
          for (k=0; k<=3; k++)
3268
 
            aggr|=posPoint->rankInSuit[k][trump];
3269
 
          h=localVar[thrId].rel[aggr].absRank[3][trump].hand;
3270
 
          if (h!=-1) {
3271
 
            if ((localVar[thrId].nodeTypeStore[h]==MINNODE)&&
3272
 
              ((posPoint->tricksMAX+(depth>>2))<target)&&
3273
 
              (depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3274
 
              for (ss=0; ss<=3; ss++)
3275
 
                posPoint->winRanks[depth][ss]=0;
3276
 
              posPoint->winRanks[depth][trump]=
3277
 
                bitMapRank[localVar[thrId].rel[aggr].absRank[3][trump].rank];
3278
 
              return FALSE;
3279
 
            }
3280
 
          }
3281
 
        }
3282
 
      }
3283
 
    }
3284
 
  }
3285
 
  return TRUE;
3286
 
}
3287
 
 
3288
 
 
3289
 
int LaterTricksMAX(struct pos *posPoint, int hand, int depth, int target,
3290
 
        int trump, int thrId) {
3291
 
  int hh, ss, k, h, sum=0;
3292
 
  unsigned short aggr;
3293
 
 
3294
 
  if ((trump==4)||(posPoint->winner[trump].rank==0)) {
3295
 
    for (ss=0; ss<=3; ss++) {
3296
 
      hh=posPoint->winner[ss].hand;
3297
 
      if (hh!=-1) {
3298
 
        if (localVar[thrId].nodeTypeStore[hh]==MINNODE)
3299
 
          sum+=Max(posPoint->length[hh][ss], posPoint->length[partner[hh]][ss]);
3300
 
      }
3301
 
    }
3302
 
    if ((posPoint->tricksMAX+(depth>>2)+1-sum>=target)&&
3303
 
        (sum>0)&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3304
 
      if ((posPoint->tricksMAX+1>=target)) {
3305
 
        for (ss=0; ss<=3; ss++) {
3306
 
          if (posPoint->winner[ss].hand==-1)
3307
 
            posPoint->winRanks[depth][ss]=0;
3308
 
          else if (localVar[thrId].nodeTypeStore[posPoint->winner[ss].hand]==MAXNODE) {
3309
 
            if ((posPoint->rankInSuit[partner[posPoint->winner[ss].hand]][ss]==0)&&
3310
 
                (posPoint->rankInSuit[lho[posPoint->winner[ss].hand]][ss]==0)&&
3311
 
                (posPoint->rankInSuit[rho[posPoint->winner[ss].hand]][ss]==0))
3312
 
                posPoint->winRanks[depth][ss]=0;
3313
 
            else
3314
 
              posPoint->winRanks[depth][ss]=bitMapRank[posPoint->winner[ss].rank];
3315
 
          }
3316
 
          else
3317
 
            posPoint->winRanks[depth][ss]=0;
3318
 
        }
3319
 
        return TRUE;
3320
 
      }
3321
 
    }
3322
 
  }
3323
 
  else if ((trump!=4) && (posPoint->winner[trump].rank!=0) &&
3324
 
    (localVar[thrId].nodeTypeStore[posPoint->winner[trump].hand]==MAXNODE)) {
3325
 
    if ((posPoint->length[hand][trump]==0)&&
3326
 
      (posPoint->length[partner[hand]][trump]==0)) {
3327
 
      if (((posPoint->tricksMAX+Max(posPoint->length[lho[hand]][trump],
3328
 
        posPoint->length[rho[hand]][trump]))>=target)
3329
 
        &&(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3330
 
        for (ss=0; ss<=3; ss++)
3331
 
          posPoint->winRanks[depth][ss]=0;
3332
 
        return TRUE;
3333
 
      }
3334
 
    }
3335
 
    else if (((posPoint->tricksMAX+1)>=target)
3336
 
      &&(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3337
 
      for (ss=0; ss<=3; ss++)
3338
 
        posPoint->winRanks[depth][ss]=0;
3339
 
      posPoint->winRanks[depth][trump]=
3340
 
          bitMapRank[posPoint->winner[trump].rank];
3341
 
      return TRUE;
3342
 
    }
3343
 
    else {
3344
 
      hh=posPoint->secondBest[trump].hand;
3345
 
      if (hh!=-1) {
3346
 
        if ((localVar[thrId].nodeTypeStore[hh]==MAXNODE)&&(posPoint->secondBest[trump].rank!=0))  {
3347
 
          if (((posPoint->length[hh][trump]>1) ||
3348
 
            (posPoint->length[partner[hh]][trump]>1))&&
3349
 
            ((posPoint->tricksMAX+2)>=target)&&(depth>0)
3350
 
            &&(depth!=localVar[thrId].iniDepth)) {
3351
 
            for (ss=0; ss<=3; ss++)
3352
 
              posPoint->winRanks[depth][ss]=0;
3353
 
            posPoint->winRanks[depth][trump]=
3354
 
            bitMapRank[posPoint->secondBest[trump].rank];
3355
 
            return TRUE;
3356
 
          }
3357
 
        }
3358
 
      }
3359
 
    }
3360
 
  }
3361
 
 
3362
 
  else if (trump!=4) {
3363
 
    hh=posPoint->secondBest[trump].hand;
3364
 
    if (hh!=-1) {
3365
 
      if ((localVar[thrId].nodeTypeStore[hh]==MAXNODE)&&
3366
 
        (posPoint->length[hh][trump]>1)) {
3367
 
        if (posPoint->winner[trump].hand==rho[hh]) {
3368
 
          if (((posPoint->tricksMAX+1)>=target)&&(depth>0)
3369
 
             &&(depth!=localVar[thrId].iniDepth)) {
3370
 
            for (ss=0; ss<=3; ss++)
3371
 
              posPoint->winRanks[depth][ss]=0;
3372
 
            posPoint->winRanks[depth][trump]=
3373
 
              bitMapRank[posPoint->secondBest[trump].rank] ;
3374
 
            return TRUE;
3375
 
          }
3376
 
        }
3377
 
        else {
3378
 
          aggr=0;
3379
 
          for (k=0; k<=3; k++)
3380
 
            aggr|=posPoint->rankInSuit[k][trump];
3381
 
          h=localVar[thrId].rel[aggr].absRank[3][trump].hand;
3382
 
          if (h!=-1) {
3383
 
            if ((localVar[thrId].nodeTypeStore[h]==MAXNODE)&&
3384
 
                ((posPoint->tricksMAX+1)>=target)&&(depth>0)
3385
 
                &&(depth!=localVar[thrId].iniDepth)) {
3386
 
              for (ss=0; ss<=3; ss++)
3387
 
                posPoint->winRanks[depth][ss]=0;
3388
 
              posPoint->winRanks[depth][trump]=
3389
 
                bitMapRank[localVar[thrId].rel[aggr].absRank[3][trump].rank];
3390
 
              return TRUE;
3391
 
            }
3392
 
          }
3393
 
        }
3394
 
      }
3395
 
    }
3396
 
  }
3397
 
  return FALSE;
3398
 
}
3399
 
 
3400
 
 
3401
 
int MoveGen(struct pos * posPoint, int depth, int trump, struct movePlyType *mply, int thrId) {
3402
 
  int suit, k, m, r, s, t, q, first, state;
3403
 
  unsigned short ris;
3404
 
 
3405
 
  int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth,
3406
 
    unsigned short notVoidInSuit, int trump, int thrId);
3407
 
  int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth,
3408
 
    unsigned short notVoidInSuit, int thrId);
3409
 
 
3410
 
  for (k=0; k<4; k++)
3411
 
    localVar[thrId].lowestWin[depth][k]=0;
3412
 
 
3413
 
  m=0;
3414
 
  r=posPoint->handRelFirst;
3415
 
  assert((r>=0)&&(r<=3));
3416
 
  first=posPoint->first[depth];
3417
 
  q=handId(first, r);
3418
 
 
3419
 
  if (r!=0) {
3420
 
    s=localVar[thrId].movePly[depth+r].current;             /* Current move of first hand */
3421
 
    t=localVar[thrId].movePly[depth+r].move[s].suit;        /* Suit played by first hand */
3422
 
    ris=posPoint->rankInSuit[q][t];
3423
 
 
3424
 
    if (ris!=0) {
3425
 
    /* Not first hand and not void in suit */
3426
 
      k=14;   state=MOVESVALID;
3427
 
      while (k>=2) {
3428
 
        if ((ris & bitMapRank[k])&&(state==MOVESVALID)) {
3429
 
           /* Only first move in sequence is generated */
3430
 
          mply->move[m].suit=t;
3431
 
          mply->move[m].rank=k;
3432
 
          mply->move[m].sequence=0;
3433
 
          m++;
3434
 
          state=MOVESLOCKED;
3435
 
        }
3436
 
        else if (state==MOVESLOCKED)
3437
 
          if ((posPoint->removedRanks[t] & bitMapRank[k])==0) {
3438
 
            if ((ris & bitMapRank[k])==0)
3439
 
            /* If the card still exists and it is not in own hand */
3440
 
              state=MOVESVALID;
3441
 
            else
3442
 
            /* If the card still exists and it is in own hand */
3443
 
              mply->move[m-1].sequence|=bitMapRank[k];
3444
 
          }
3445
 
        k--;
3446
 
      }
3447
 
      if (m!=1) {
3448
 
        if ((trump!=4)&&(posPoint->winner[trump].rank!=0)) {
3449
 
          for (k=0; k<=m-1; k++)
3450
 
            mply->move[k].weight=WeightAllocTrump(posPoint,
3451
 
              &(mply->move[k]), depth, ris, trump, thrId);
3452
 
        }
3453
 
        else {
3454
 
          for (k=0; k<=m-1; k++)
3455
 
            mply->move[k].weight=WeightAllocNT(posPoint,
3456
 
              &(mply->move[k]), depth, ris, thrId);
3457
 
        }
3458
 
      }
3459
 
 
3460
 
      mply->last=m-1;
3461
 
      if (m!=1)
3462
 
        MergeSort(m, mply->move);
3463
 
      if (depth!=localVar[thrId].iniDepth)
3464
 
        return m;
3465
 
      else {
3466
 
        m=AdjustMoveList(thrId);
3467
 
        return m;
3468
 
      }
3469
 
    }
3470
 
  }
3471
 
 
3472
 
  /* First hand or void in suit */
3473
 
  for (suit=0; suit<=3; suit++)  {
3474
 
    k=14;  state=MOVESVALID;
3475
 
    while (k>=2) {
3476
 
      if ((posPoint->rankInSuit[q][suit] & bitMapRank[k])&&
3477
 
            (state==MOVESVALID)) {
3478
 
           /* Only first move in sequence is generated */
3479
 
        mply->move[m].suit=suit;
3480
 
        mply->move[m].rank=k;
3481
 
        mply->move[m].sequence=0;
3482
 
        m++;
3483
 
        state=MOVESLOCKED;
3484
 
      }
3485
 
      else if (state==MOVESLOCKED)
3486
 
        if ((posPoint->removedRanks[suit] & bitMapRank[k])==0) {
3487
 
          if ((posPoint->rankInSuit[q][suit] & bitMapRank[k])==0)
3488
 
            /* If the card still exists and it is not in own hand */
3489
 
            state=MOVESVALID;
3490
 
          else
3491
 
            /* If the card still exists and it is in own hand */
3492
 
            mply->move[m-1].sequence|=bitMapRank[k];
3493
 
      }
3494
 
      k--;
3495
 
    }
3496
 
  }
3497
 
 
3498
 
  if ((trump!=4)&&(posPoint->winner[trump].rank!=0)) {
3499
 
    for (k=0; k<=m-1; k++)
3500
 
      mply->move[k].weight=WeightAllocTrump(posPoint,
3501
 
          &(mply->move[k]), depth, 0/*ris*/, trump, thrId);
3502
 
  }
3503
 
  else {
3504
 
    for (k=0; k<=m-1; k++)
3505
 
      mply->move[k].weight=WeightAllocNT(posPoint,
3506
 
          &(mply->move[k]), depth, 0/*ris*/, thrId);
3507
 
  }
3508
 
 
3509
 
  mply->last=m-1;
3510
 
  if (m!=1)
3511
 
    MergeSort(m, mply->move);
3512
 
 
3513
 
  if (depth!=localVar[thrId].iniDepth)
3514
 
    return m;
3515
 
  else {
3516
 
    m=AdjustMoveList(thrId);
3517
 
    return m;
3518
 
  }
3519
 
}
3520
 
 
3521
 
 
3522
 
int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth,
3523
 
  unsigned short notVoidInSuit, int thrId) {
3524
 
  int weight=0, k, l, kk, ll, suit, suitAdd=0, leadSuit;
3525
 
  int suitWeightDelta, first, q;
3526
 
  int rRank, thirdBestHand;
3527
 
  int winMove=FALSE;    /* If winMove is true, current move can win the current trick. */
3528
 
  unsigned short suitCount, suitCountLH, suitCountRH, aggr;
3529
 
  int countLH, countRH;
3530
 
 
3531
 
  first=posPoint->first[depth];
3532
 
  q=handId(first, posPoint->handRelFirst);
3533
 
  suit=mp->suit;
3534
 
  aggr=0;
3535
 
  for (k=0; k<=3; k++)
3536
 
    aggr|=posPoint->rankInSuit[k][suit];
3537
 
  rRank=localVar[thrId].rel[aggr].relRank[mp->rank][suit];
3538
 
 
3539
 
  switch (posPoint->handRelFirst) {
3540
 
    case 0:
3541
 
      thirdBestHand=localVar[thrId].rel[aggr].absRank[3][suit].hand;
3542
 
      suitCount=posPoint->length[q][suit];
3543
 
      suitCountLH=posPoint->length[lho[q]][suit];
3544
 
      suitCountRH=posPoint->length[rho[q]][suit];
3545
 
 
3546
 
      if (suitCountLH!=0) {
3547
 
          countLH=(suitCountLH<<2);
3548
 
      }
3549
 
      else
3550
 
        countLH=depth+4;
3551
 
 
3552
 
      if (suitCountRH!=0) {
3553
 
          countRH=(suitCountRH<<2);
3554
 
      }
3555
 
      else
3556
 
        countRH=depth+4;
3557
 
 
3558
 
      /* Discourage a suit selection where the search tree appears larger than for the
3559
 
      altenative suits: the search is estimated to be small when the added number of
3560
 
      alternative cards to play for the opponents is small. */ 
3561
 
 
3562
 
      suitWeightDelta=-((countLH+countRH)<<5)/19;       
3563
 
          
3564
 
      if (posPoint->winner[suit].rank==mp->rank) 
3565
 
        winMove=TRUE;                      
3566
 
      else if (posPoint->rankInSuit[partner[first]][suit] >
3567
 
        (posPoint->rankInSuit[lho[first]][suit] |
3568
 
           posPoint->rankInSuit[rho[first]][suit])) {
3569
 
        winMove=TRUE;
3570
 
      }                 
3571
 
              
3572
 
      if (winMove) {
3573
 
        /* Discourage suit if RHO has second best card.
3574
 
           Exception: RHO has singleton. */
3575
 
        if (posPoint->secondBest[suit].hand==rho[q]) {
3576
 
          if (suitCountRH!=1)
3577
 
            suitWeightDelta-=7;
3578
 
        }
3579
 
        /* Encourage playing suit if LHO has second highest rank. */
3580
 
        else if (posPoint->secondBest[suit].hand==lho[q]) 
3581
 
          suitWeightDelta+=14;
3582
 
          
3583
 
        /* Higher weight if also second best rank is present on current side to play, or
3584
 
        if second best is a singleton at LHO or RHO. */
3585
 
 
3586
 
        if (((posPoint->secondBest[suit].hand!=lho[first])
3587
 
           ||(suitCountLH==1))&&
3588
 
           ((posPoint->secondBest[suit].hand!=rho[first])
3589
 
           ||(suitCountRH==1)))
3590
 
          weight=suitWeightDelta+41/*48*/+rRank;
3591
 
 
3592
 
        /* Encourage playing second highest rank if hand also has
3593
 
        third highest rank. */
3594
 
 
3595
 
        else if ((mp->sequence)&&
3596
 
          (mp->rank==posPoint->secondBest[suit].rank))                  
3597
 
          weight=suitWeightDelta+39;
3598
 
        else
3599
 
          weight=suitWeightDelta+20+rRank;
3600
 
 
3601
 
        /* Encourage playing cards that previously caused search cutoff
3602
 
        or was stored as the best move in a transposition table entry match. */
3603
 
 
3604
 
        if ((localVar[thrId].bestMove[depth].suit==suit)&&
3605
 
          (localVar[thrId].bestMove[depth].rank==mp->rank)) 
3606
 
          weight+=123/*122*//*112*//*73*/;
3607
 
        else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&&
3608
 
          (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) 
3609
 
          weight+=24/*20*//*17*//*14*/;
3610
 
      }
3611
 
      else {
3612
 
        /* Discourage suit if RHO has winning or second best card.
3613
 
           Exception: RHO has singleton. */
3614
 
 
3615
 
        if ((posPoint->winner[suit].hand==rho[q])||
3616
 
          (posPoint->secondBest[suit].hand==rho[q])) {
3617
 
          if (suitCountRH!=1)
3618
 
            suitWeightDelta-=7; 
3619
 
        }
3620
 
 
3621
 
 
3622
 
        /* Try suit if LHO has winning card and partner second best. 
3623
 
             Exception: partner has singleton. */ 
3624
 
 
3625
 
        else if ((posPoint->winner[suit].hand==lho[q])&&
3626
 
          (posPoint->secondBest[suit].hand==partner[q])) {
3627
 
 
3628
 
        /* This case was suggested by Jo�l Bradmetz. */
3629
 
 
3630
 
          if (posPoint->length[partner[q]][suit]!=1)
3631
 
            suitWeightDelta+=31/*34*//*37*//*32*//*20*/;
3632
 
        }
3633
 
     
3634
 
        /* Encourage playing the suit if the hand together with partner have both the 2nd highest
3635
 
        and the 3rd highest cards such that the side of the hand has the highest card in the
3636
 
        next round playing this suit. */
3637
 
 
3638
 
        if ((posPoint->secondBest[suit].hand==partner[first])&&(partner[first]==thirdBestHand))
3639
 
          suitWeightDelta+=22/*10*/;
3640
 
        else if(((posPoint->secondBest[suit].hand==first)&&(partner[first]==thirdBestHand)&&
3641
 
          (posPoint->length[partner[first]][suit]>1))||((posPoint->secondBest[suit].hand==partner[first])&&
3642
 
          (first==thirdBestHand)&&(posPoint->length[partner[first]][suit]>1)))
3643
 
          suitWeightDelta+=24/*10*/;    
3644
 
 
3645
 
        /* Higher weight if LHO or RHO has the highest (winning) card as a singleton. */
3646
 
 
3647
 
        if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first]))
3648
 
            ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first])))
3649
 
          weight=suitWeightDelta+25/*23*//*22*/+rRank;
3650
 
        else if (posPoint->winner[suit].hand==first) {
3651
 
          weight=suitWeightDelta-20/*24*//*27*//*12*//*10*/+rRank;
3652
 
        }
3653
 
 
3654
 
        /* Encourage playing second highest rank if hand also has
3655
 
        third highest rank. */
3656
 
 
3657
 
        else if ((mp->sequence)&&
3658
 
          (mp->rank==posPoint->secondBest[suit].rank)) 
3659
 
          weight=suitWeightDelta+44/*42*/;
3660
 
        else if (mp->sequence)
3661
 
          weight=suitWeightDelta+31/*32*/-rRank;
3662
 
        else 
3663
 
          weight=suitWeightDelta+12+rRank; 
3664
 
        
3665
 
        /* Encourage playing cards that previously caused search cutoff
3666
 
        or was stored as the best move in a transposition table entry match. */
3667
 
 
3668
 
        if ((localVar[thrId].bestMove[depth].suit==suit)&&
3669
 
            (localVar[thrId].bestMove[depth].rank==mp->rank)) 
3670
 
          weight+=47/*45*//*39*//*38*/;
3671
 
        else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&&
3672
 
            (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) 
3673
 
          weight+=13/*15*//*16*//*19*//*14*/;
3674
 
      }
3675
 
        
3676
 
      break;
3677
 
 
3678
 
    case 1:
3679
 
      leadSuit=posPoint->move[depth+1].suit;
3680
 
      if (leadSuit==suit) {
3681
 
        if (bitMapRank[mp->rank]>
3682
 
            (bitMapRank[posPoint->move[depth+1].rank] |
3683
 
            posPoint->rankInSuit[partner[first]][suit])) 
3684
 
          winMove=TRUE;
3685
 
        else if (posPoint->rankInSuit[rho[first]][suit]>
3686
 
           (bitMapRank[posPoint->move[depth+1].rank] |
3687
 
            posPoint->rankInSuit[partner[first]][suit])) 
3688
 
          winMove=TRUE;
3689
 
      }
3690
 
      else {
3691
 
        /* Side with highest rank in leadSuit wins */
3692
 
 
3693
 
        if (posPoint->rankInSuit[rho[first]][leadSuit] >
3694
 
           (posPoint->rankInSuit[partner[first]][leadSuit] |
3695
 
            bitMapRank[posPoint->move[depth+1].rank]))
3696
 
          winMove=TRUE;                                           
3697
 
      }
3698
 
      
3699
 
      if (winMove) {
3700
 
        if (!notVoidInSuit) { 
3701
 
          suitCount=posPoint->length[q][suit];
3702
 
          suitAdd=(suitCount<<6)/(23/*20*//*21*//*24*//*30*//*35*/);
3703
 
          if (posPoint->secondBest[suit].hand==q) {
3704
 
          /* Discourage suit discard if 2nd highest card becomes singleton. */
3705
 
 
3706
 
            if (suitCount==2)
3707
 
              suitAdd-=3;
3708
 
          }
3709
 
          /* Discourage suit discard of highest card. */
3710
 
 
3711
 
          else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) 
3712
 
            suitAdd-=3;
3713
 
 
3714
 
          /*Encourage discard of low cards in long suits. */
3715
 
            weight=/*60*/-(mp->rank)+suitAdd;           
3716
 
        }
3717
 
        else {  
3718
 
          weight=80+rRank;
3719
 
        } 
3720
 
      }
3721
 
      else {
3722
 
        if (!notVoidInSuit) {
3723
 
          suitCount=posPoint->length[q][suit];
3724
 
          suitAdd=(suitCount<<6)/33; 
3725
 
 
3726
 
          /* Discourage suit discard if 2nd highest card becomes singleton. */ 
3727
 
          if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
3728
 
            suitAdd-=7; 
3729
 
                  
3730
 
          /* Discourage suit discard of highest card. */
3731
 
          else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) 
3732
 
            suitAdd-=10;
3733
 
 
3734
 
          /*Encourage discard of low cards in long suits. */
3735
 
          weight=-(mp->rank)+suitAdd; 
3736
 
        }
3737
 
        else {
3738
 
 
3739
 
          /* If lowest rank for either partner to leading hand 
3740
 
          or rho is higher than played card for lho,
3741
 
          lho should play as low card as possible */
3742
 
        
3743
 
          kk=posPoint->rankInSuit[partner[first]][leadSuit];
3744
 
          ll=posPoint->rankInSuit[rho[first]][leadSuit];
3745
 
          k=kk & (-kk); l=ll & (-ll);  /* Only least significant 1 bit of
3746
 
                                        bit map ranks for partner and RHO. */
3747
 
 
3748
 
          if ((k > bitMapRank[mp->rank])||(l > bitMapRank[mp->rank])) 
3749
 
            weight=-3+rRank;            
3750
 
          else if (mp->rank > posPoint->move[depth+1].rank) {
3751
 
            if (mp->sequence) { 
3752
 
              weight=/*0*/10+rRank;     
3753
 
            }
3754
 
            else { 
3755
 
              weight=13-(mp->rank);
3756
 
              /*weight=-5+rRank;*/
3757
 
            }
3758
 
          }          
3759
 
          else {
3760
 
            weight=-15+rRank;           
3761
 
          }     
3762
 
        }
3763
 
      }
3764
 
 
3765
 
      break;
3766
 
 
3767
 
    case 2:
3768
 
            
3769
 
      leadSuit=posPoint->move[depth+2].suit;
3770
 
      if (WinningMoveNT(mp, &(posPoint->move[depth+1]),thrId)) {
3771
 
        if (bitMapRank[mp->rank] >
3772
 
          posPoint->rankInSuit[rho[first]][suit])
3773
 
          winMove=TRUE;
3774
 
      } 
3775
 
      else if (posPoint->high[depth+1]==first) {
3776
 
        if (posPoint->rankInSuit[rho[first]][leadSuit]
3777
 
              < bitMapRank[posPoint->move[depth+2].rank])       
3778
 
          winMove=TRUE;
3779
 
        
3780
 
      }
3781
 
      
3782
 
      if (winMove) {
3783
 
        if (!notVoidInSuit) {
3784
 
          suitCount=posPoint->length[q][suit];
3785
 
          suitAdd=(suitCount<<6)/(17/*27*//*30*//*35*/);
3786
 
 
3787
 
          /* Discourage suit discard if 2nd highest card becomes singleton. */ 
3788
 
          if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
3789
 
            suitAdd-=(6/*2*//*5*/);     
3790
 
          weight=-(mp->rank)+suitAdd;  
3791
 
        }
3792
 
        else { 
3793
 
          weight=60+rRank;
3794
 
        }
3795
 
      }
3796
 
      else {
3797
 
        if (!notVoidInSuit) {
3798
 
          suitCount=posPoint->length[q][suit];
3799
 
          suitAdd=(suitCount<<6)/(24/*26*//*29*//*35*/);   
3800
 
          if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
3801
 
            suitAdd-=(4/*5*/);  
3802
 
           /* Discourage suit discard of highest card. */
3803
 
          else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) 
3804
 
            suitAdd-=(4/*5*/);  
3805
 
 
3806
 
          weight=-(mp->rank)+suitAdd;   
3807
 
 
3808
 
        }
3809
 
        else {
3810
 
                  
3811
 
          k=posPoint->rankInSuit[rho[first]][suit];
3812
 
          if ((k & (-k)) > bitMapRank[mp->rank])
3813
 
            weight=-(mp->rank);
3814
 
          else if (WinningMoveNT(mp, &(posPoint->move[depth+1]), thrId)) {
3815
 
            if ((mp->rank==posPoint->secondBest[leadSuit].rank)&&
3816
 
                                (mp->sequence))
3817
 
              weight=25;                
3818
 
            else if (mp->sequence)
3819
 
              weight=20-(mp->rank);  
3820
 
            else
3821
 
              weight=10-(mp->rank);  
3822
 
          }
3823
 
          else  
3824
 
            weight=-10-(mp->rank);  
3825
 
        } 
3826
 
      }
3827
 
            
3828
 
      break;
3829
 
 
3830
 
    case 3:
3831
 
      if (!notVoidInSuit) {
3832
 
        suitCount=posPoint->length[q][suit];
3833
 
        suitAdd=(suitCount<<6)/(27/*35*/);   
3834
 
        if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
3835
 
          suitAdd-=(6/*5*/);                            
3836
 
        else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) 
3837
 
          suitAdd-=(8/*9*//*8*//*5*/);  
3838
 
 
3839
 
        weight=30-(mp->rank)+suitAdd;
3840
 
      }
3841
 
      else if ((posPoint->high[depth+1])==(lho[first])) {
3842
 
        /* If the current winning move is given by the partner */
3843
 
        weight=30-(mp->rank);           
3844
 
      }
3845
 
      else if (WinningMoveNT(mp, &(posPoint->move[depth+1]),thrId))
3846
 
        /* If present move is superior to current winning move and the
3847
 
        current winning move is not given by the partner */
3848
 
        weight=30-(mp->rank);           
3849
 
      else {
3850
 
        /* If present move is not superior to current winning move and the
3851
 
        current winning move is not given by the partner */
3852
 
        weight=14-(mp->rank);           
3853
 
      }
3854
 
  }
3855
 
  return weight;
3856
 
}
3857
 
 
3858
 
 
3859
 
int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth,
3860
 
  unsigned short notVoidInSuit, int trump, int thrId) {
3861
 
  int weight=0, k, l, kk, ll, suit, suitAdd=0, leadSuit;
3862
 
  int suitWeightDelta, first, q, rRank, thirdBestHand;
3863
 
  int suitBonus=0;
3864
 
  int winMove=FALSE;    /* If winMove is true, current move can win the current trick. */
3865
 
  unsigned short suitCount, suitCountLH, suitCountRH, aggr;
3866
 
  int countLH, countRH;
3867
 
 
3868
 
  first=posPoint->first[depth];
3869
 
  q=handId(first, posPoint->handRelFirst);
3870
 
  suit=mp->suit;
3871
 
  aggr=0;
3872
 
  for (k=0; k<=3; k++)
3873
 
    aggr|=posPoint->rankInSuit[k][suit];
3874
 
  rRank=localVar[thrId].rel[aggr].relRank[mp->rank][suit];
3875
 
 
3876
 
  switch (posPoint->handRelFirst) {
3877
 
    case 0:
3878
 
      thirdBestHand=localVar[thrId].rel[aggr].absRank[3][suit].hand;
3879
 
      suitCount=posPoint->length[q][suit];
3880
 
      suitCountLH=posPoint->length[lho[q]][suit];
3881
 
      suitCountRH=posPoint->length[rho[q]][suit];
3882
 
 
3883
 
      /* Discourage suit if LHO or RHO can ruff. */
3884
 
 
3885
 
      if ((suit!=trump) &&
3886
 
        (((posPoint->rankInSuit[lho[q]][suit]==0) &&
3887
 
          (posPoint->rankInSuit[lho[q]][trump]!=0)) ||
3888
 
          ((posPoint->rankInSuit[rho[q]][suit]==0) &&
3889
 
          (posPoint->rankInSuit[rho[q]][trump]!=0))))
3890
 
        suitBonus=-17/*20*//*-10*/;
3891
 
            
3892
 
      /* Encourage suit if partner can ruff. */
3893
 
 
3894
 
      if ((suit!=trump)&&(posPoint->length[partner[q]][suit]==0)&&
3895
 
             (posPoint->length[partner[q]][trump]>0)&&(suitCountRH>0))
3896
 
        suitBonus+=26/*28*/;
3897
 
 
3898
 
      /* Discourage suit if RHO has high card. */
3899
 
 
3900
 
      if ((posPoint->winner[suit].hand==rho[q])||
3901
 
          (posPoint->secondBest[suit].hand==rho[q])) {
3902
 
        if (suitCountRH!=1)
3903
 
          suitBonus-=11/*12*//*13*//*18*/;
3904
 
      }
3905
 
 
3906
 
      /* Try suit if LHO has winning card and partner second best. 
3907
 
      Exception: partner has singleton. */ 
3908
 
 
3909
 
      else if ((posPoint->winner[suit].hand==lho[q])&&
3910
 
        (posPoint->secondBest[suit].hand==partner[q])) {
3911
 
 
3912
 
        /* This case was suggested by Jo�l Bradmetz. */
3913
 
 
3914
 
        if (posPoint->length[partner[q]][suit]!=1) 
3915
 
          suitBonus+=30/*28*//*22*/;
3916
 
      }
3917
 
 
3918
 
      /* Encourage play of suit where partner wins and
3919
 
      returns the suit for a ruff. */
3920
 
      if ((suit!=trump)&&(suitCount==1)&&
3921
 
        (posPoint->length[q][trump]>0)&&
3922
 
        (posPoint->length[partner[q]][suit]>1)&&
3923
 
        (posPoint->winner[suit].hand==partner[q]))
3924
 
        suitBonus+=23/*24*//*19*//*16*/;
3925
 
 
3926
 
      if (suitCountLH!=0)
3927
 
        countLH=(suitCountLH<<2);
3928
 
      else
3929
 
        countLH=depth+4;
3930
 
      if (suitCountRH!=0)
3931
 
        countRH=(suitCountRH<<2);
3932
 
      else
3933
 
        countRH=depth+4;
3934
 
 
3935
 
      /* Discourage a suit selection where the search tree appears larger than for the
3936
 
          altenative suits: the search is estimated to be small when the added number of
3937
 
          alternative cards to play for the opponents is small. */ 
3938
 
 
3939
 
      suitWeightDelta=suitBonus-
3940
 
        ((countLH+countRH)<<5)/(12/*15*/);
3941
 
 
3942
 
      if (posPoint->winner[suit].rank==mp->rank) {
3943
 
        if ((suit!=trump)) {
3944
 
          if ((posPoint->length[partner[first]][suit]!=0)||
3945
 
            (posPoint->length[partner[first]][trump]==0)) {
3946
 
            if (((posPoint->length[lho[first]][suit]!=0)||
3947
 
                  (posPoint->length[lho[first]][trump]==0))&&
3948
 
                  ((posPoint->length[rho[first]][suit]!=0)||
3949
 
                  (posPoint->length[rho[first]][trump]==0)))
3950
 
              winMove=TRUE;
3951
 
          }
3952
 
          else if (((posPoint->length[lho[first]][suit]!=0)||
3953
 
               (posPoint->rankInSuit[partner[first]][trump]>
3954
 
                posPoint->rankInSuit[lho[first]][trump]))&&
3955
 
                ((posPoint->length[rho[first]][suit]!=0)||
3956
 
                (posPoint->rankInSuit[partner[first]][trump]>
3957
 
                 posPoint->rankInSuit[rho[first]][trump])))
3958
 
            winMove=TRUE;
3959
 
        }
3960
 
        else 
3961
 
          winMove=TRUE;                    
3962
 
      }
3963
 
      else if (posPoint->rankInSuit[partner[first]][suit] >
3964
 
        (posPoint->rankInSuit[lho[first]][suit] |
3965
 
        posPoint->rankInSuit[rho[first]][suit])) {
3966
 
        if (suit!=trump) {
3967
 
          if (((posPoint->length[lho[first]][suit]!=0)||
3968
 
              (posPoint->length[lho[first]][trump]==0))&&
3969
 
              ((posPoint->length[rho[first]][suit]!=0)||
3970
 
              (posPoint->length[rho[first]][trump]==0)))
3971
 
            winMove=TRUE;
3972
 
        }
3973
 
        else
3974
 
          winMove=TRUE;
3975
 
      }                 
3976
 
      else if (suit!=trump) {
3977
 
        if ((posPoint->length[partner[first]][suit]==0)&&
3978
 
            (posPoint->length[partner[first]][trump]!=0)) {
3979
 
          if ((posPoint->length[lho[first]][suit]==0)&&
3980
 
              (posPoint->length[lho[first]][trump]!=0)&&
3981
 
                  (posPoint->length[rho[first]][suit]==0)&&
3982
 
              (posPoint->length[rho[first]][trump]!=0)) {
3983
 
            if (posPoint->rankInSuit[partner[first]][trump]>
3984
 
               (posPoint->rankInSuit[lho[first]][trump] |
3985
 
                posPoint->rankInSuit[rho[first]][trump]))
3986
 
              winMove=TRUE;
3987
 
          }
3988
 
          else if ((posPoint->length[lho[first]][suit]==0)&&
3989
 
              (posPoint->length[lho[first]][trump]!=0)) {
3990
 
            if (posPoint->rankInSuit[partner[first]][trump]
3991
 
                    > posPoint->rankInSuit[lho[first]][trump])
3992
 
                winMove=TRUE;
3993
 
          }     
3994
 
          else if ((posPoint->length[rho[first]][suit]==0)&&
3995
 
              (posPoint->length[rho[first]][trump]!=0)) {
3996
 
            if (posPoint->rankInSuit[partner[first]][trump]
3997
 
                    > posPoint->rankInSuit[rho[first]][trump])
3998
 
              winMove=TRUE;
3999
 
          }     
4000
 
          else
4001
 
            winMove=TRUE;
4002
 
        }
4003
 
      }
4004
 
              
4005
 
      if (winMove) {
4006
 
 
4007
 
        /* Encourage ruffing LHO or RHO singleton, highest card. */
4008
 
 
4009
 
        if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first]))
4010
 
            ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first])))
4011
 
          weight=suitWeightDelta+39+rRank;
4012
 
 
4013
 
        /* Lead hand has the highest card. */
4014
 
 
4015
 
        else if (posPoint->winner[suit].hand==first) {
4016
 
 
4017
 
        /* Also, partner has second highest card. */
4018
 
 
4019
 
          if (posPoint->secondBest[suit].hand==partner[first])
4020
 
            weight=suitWeightDelta+46+rRank;
4021
 
          else if (posPoint->winner[suit].rank==mp->rank)
4022
 
 
4023
 
            /* If the current card to play is the highest card. */
4024
 
 
4025
 
            weight=suitWeightDelta+31;
4026
 
          else
4027
 
            weight=suitWeightDelta-2+rRank;
4028
 
        }
4029
 
        else if (posPoint->winner[suit].hand==partner[first]) {
4030
 
          /* If partner has highest card */
4031
 
          if (posPoint->secondBest[suit].hand==first)
4032
 
            weight=suitWeightDelta+35/*35*//*46*//*50*/+rRank;
4033
 
          else 
4034
 
            weight=suitWeightDelta+24/*35*/+rRank;  
4035
 
        } 
4036
 
        /* Encourage playing second highest rank if hand also has
4037
 
        third highest rank. */
4038
 
 
4039
 
        else if ((mp->sequence)&&
4040
 
          (mp->rank==posPoint->secondBest[suit].rank))                  
4041
 
          weight=suitWeightDelta+41;
4042
 
        else if (mp->sequence)
4043
 
          weight=suitWeightDelta+17+rRank;
4044
 
        else
4045
 
          weight=suitWeightDelta+11+rRank;
4046
 
 
4047
 
        /* Encourage playing cards that previously caused search cutoff
4048
 
        or was stored as the best move in a transposition table entry match. */
4049
 
 
4050
 
        if ((localVar[thrId].bestMove[depth].suit==suit)&&
4051
 
            (localVar[thrId].bestMove[depth].rank==mp->rank)) 
4052
 
          weight+=53/*50*//*52*/;
4053
 
        else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&&
4054
 
            (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) 
4055
 
          weight+=14/*15*//*12*//*11*/;
4056
 
      }
4057
 
      else {
4058
 
 
4059
 
        /* Encourage playing the suit if the hand together with partner have both the 2nd highest
4060
 
        and the 3rd highest cards such that the side of the hand has the highest card in the
4061
 
        next round playing this suit. */
4062
 
 
4063
 
        if ((posPoint->secondBest[suit].hand==partner[first])&&(partner[first]==thirdBestHand))
4064
 
           suitWeightDelta+=20/*22*/;
4065
 
        else if(((posPoint->secondBest[suit].hand==first)&&(partner[first]==thirdBestHand)&&
4066
 
          (posPoint->length[partner[first]][suit]>1))||
4067
 
          ((posPoint->secondBest[suit].hand==partner[first])&&
4068
 
          (first==thirdBestHand)&&(posPoint->length[partner[first]][suit]>1)))
4069
 
           suitWeightDelta+=20/*24*/;
4070
 
        
4071
 
        /* Higher weight if LHO or RHO has the highest (winning) card as a singleton. */
4072
 
 
4073
 
        if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first]))
4074
 
            ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first])))
4075
 
          weight=suitWeightDelta+rRank-2;
4076
 
        else if (posPoint->winner[suit].hand==first) {
4077
 
          if (posPoint->secondBest[suit].hand==partner[first])
4078
 
 
4079
 
          /* Opponents win by ruffing */
4080
 
 
4081
 
            weight=suitWeightDelta+33+rRank;
4082
 
          else if (posPoint->winner[suit].rank==mp->rank) 
4083
 
 
4084
 
          /* Opponents win by ruffing */
4085
 
 
4086
 
            weight=suitWeightDelta+36;
4087
 
          else
4088
 
            weight=suitWeightDelta-17+rRank;
4089
 
        }
4090
 
        else if (posPoint->winner[suit].hand==partner[first]) {
4091
 
 
4092
 
          /* Opponents win by ruffing */
4093
 
 
4094
 
          weight=suitWeightDelta+33+rRank;
4095
 
        } 
4096
 
        /* Encourage playing second highest rank if hand also has
4097
 
        third highest rank. */
4098
 
 
4099
 
        else if ((mp->sequence)&&
4100
 
          (mp->rank==posPoint->secondBest[suit].rank)) 
4101
 
          weight=suitWeightDelta+31;
4102
 
        else 
4103
 
          weight=suitWeightDelta+13-(mp->rank);
4104
 
        
4105
 
        /* Encourage playing cards that previously caused search cutoff
4106
 
        or was stored as the best move in a transposition table entry match. */
4107
 
 
4108
 
        if ((localVar[thrId].bestMove[depth].suit==suit)&&
4109
 
            (localVar[thrId].bestMove[depth].rank==mp->rank)) 
4110
 
          weight+=17;
4111
 
        else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&&
4112
 
            (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) 
4113
 
          weight+=(3/*4*//*10*//*9*/);
4114
 
      }
4115
 
        
4116
 
      break;
4117
 
 
4118
 
    case 1:
4119
 
      leadSuit=posPoint->move[depth+1].suit;
4120
 
      if (leadSuit==suit) {
4121
 
        if (bitMapRank[mp->rank]>
4122
 
            (bitMapRank[posPoint->move[depth+1].rank] |
4123
 
            posPoint->rankInSuit[partner[first]][suit])) {
4124
 
          if (suit!=trump) {
4125
 
            if ((posPoint->length[partner[first]][suit]!=0)||
4126
 
                  (posPoint->length[partner[first]][trump]==0))
4127
 
              winMove=TRUE;
4128
 
            else if ((posPoint->length[rho[first]][suit]==0)
4129
 
                &&(posPoint->length[rho[first]][trump]!=0)
4130
 
                &&(posPoint->rankInSuit[rho[first]][trump]>
4131
 
                 posPoint->rankInSuit[partner[first]][trump]))
4132
 
              winMove=TRUE;
4133
 
          }
4134
 
          else
4135
 
            winMove=TRUE;
4136
 
        }
4137
 
        else if (posPoint->rankInSuit[rho[first]][suit]>
4138
 
            (bitMapRank[posPoint->move[depth+1].rank] |
4139
 
            posPoint->rankInSuit[partner[first]][suit])) {       
4140
 
          if (suit!=trump) {
4141
 
            if ((posPoint->length[partner[first]][suit]!=0)||
4142
 
                  (posPoint->length[partner[first]][trump]==0))
4143
 
              winMove=TRUE;
4144
 
          }
4145
 
          else
4146
 
            winMove=TRUE;
4147
 
        } 
4148
 
        else if (bitMapRank[posPoint->move[depth+1].rank] >
4149
 
            (posPoint->rankInSuit[rho[first]][suit] |
4150
 
             posPoint->rankInSuit[partner[first]][suit] |
4151
 
             bitMapRank[mp->rank])) {  
4152
 
          if (suit!=trump) {
4153
 
            if ((posPoint->length[rho[first]][suit]==0)&&
4154
 
                  (posPoint->length[rho[first]][trump]!=0)) {
4155
 
              if ((posPoint->length[partner[first]][suit]!=0)||
4156
 
                    (posPoint->length[partner[first]][trump]==0))
4157
 
                winMove=TRUE;
4158
 
              else if (posPoint->rankInSuit[rho[first]][trump]
4159
 
                  > posPoint->rankInSuit[partner[first]][trump])
4160
 
                winMove=TRUE;
4161
 
            }     
4162
 
          }
4163
 
        }       
4164
 
        else {   /* winnerHand is partner to first */
4165
 
          if (suit!=trump) {
4166
 
            if ((posPoint->length[rho[first]][suit]==0)&&
4167
 
                  (posPoint->length[rho[first]][trump]!=0))
4168
 
               winMove=TRUE;
4169
 
          }  
4170
 
        }
4171
 
      }
4172
 
      else {
4173
 
 
4174
 
         /* Leading suit differs from suit played by LHO */
4175
 
 
4176
 
        if (suit==trump) {
4177
 
          if (posPoint->length[partner[first]][leadSuit]!=0)
4178
 
            winMove=TRUE;
4179
 
          else if (bitMapRank[mp->rank]>
4180
 
                posPoint->rankInSuit[partner[first]][trump]) 
4181
 
            winMove=TRUE;
4182
 
          else if ((posPoint->length[rho[first]][leadSuit]==0)
4183
 
              &&(posPoint->length[rho[first]][trump]!=0)&&
4184
 
              (posPoint->rankInSuit[rho[first]][trump] >
4185
 
              posPoint->rankInSuit[partner[first]][trump]))
4186
 
            winMove=TRUE;
4187
 
        }       
4188
 
        else if (leadSuit!=trump) {
4189
 
 
4190
 
          /* Neither suit nor leadSuit is trump */
4191
 
 
4192
 
          if (posPoint->length[partner[first]][leadSuit]!=0) {
4193
 
            if (posPoint->rankInSuit[rho[first]][leadSuit] >
4194
 
              (posPoint->rankInSuit[partner[first]][leadSuit] |
4195
 
              bitMapRank[posPoint->move[depth+1].rank]))
4196
 
              winMove=TRUE;
4197
 
            else if ((posPoint->length[rho[first]][leadSuit]==0)
4198
 
                  &&(posPoint->length[rho[first]][trump]!=0))
4199
 
              winMove=TRUE;
4200
 
          }
4201
 
 
4202
 
          /* Partner to leading hand is void in leading suit */
4203
 
 
4204
 
          else if ((posPoint->length[rho[first]][leadSuit]==0)
4205
 
                &&(posPoint->rankInSuit[rho[first]][trump]>
4206
 
              posPoint->rankInSuit[partner[first]][trump]))
4207
 
            winMove=TRUE;
4208
 
          else if ((posPoint->length[partner[first]][trump]==0)
4209
 
              &&(posPoint->rankInSuit[rho[first]][leadSuit] >
4210
 
                bitMapRank[posPoint->move[depth+1].rank]))
4211
 
            winMove=TRUE;
4212
 
        }
4213
 
        else {
4214
 
          /* Either no trumps or leadSuit is trump, side with
4215
 
                highest rank in leadSuit wins */
4216
 
          if (posPoint->rankInSuit[rho[first]][leadSuit] >
4217
 
            (posPoint->rankInSuit[partner[first]][leadSuit] |
4218
 
             bitMapRank[posPoint->move[depth+1].rank]))
4219
 
            winMove=TRUE;                          
4220
 
        }                         
4221
 
      }
4222
 
      
4223
 
          
4224
 
      kk=posPoint->rankInSuit[partner[first]][leadSuit];
4225
 
      ll=posPoint->rankInSuit[rho[first]][leadSuit];
4226
 
      k=kk & (-kk); l=ll & (-ll);  /* Only least significant 1 bit of
4227
 
                                   bit map ranks for partner and RHO. */
4228
 
 
4229
 
      if (winMove) {
4230
 
        if (!notVoidInSuit) { 
4231
 
          suitCount=posPoint->length[q][suit];
4232
 
          suitAdd=(suitCount<<6)/(43/*36*/);
4233
 
 
4234
 
          /* Discourage suit discard if 2nd highest card becomes singleton. */ 
4235
 
 
4236
 
          if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
4237
 
            suitAdd-=2;
4238
 
 
4239
 
          if (suit==trump)  
4240
 
                weight=25/*23*/-(mp->rank)+suitAdd;
4241
 
          else
4242
 
            weight=60-(mp->rank)+suitAdd;  /* Better discard than ruff since rho
4243
 
                                                                wins anyway */          
4244
 
        } 
4245
 
        else if (k > bitMapRank[mp->rank])
4246
 
          weight=40/*41*/+rRank;
4247
 
 
4248
 
          /* If lowest card for partner to leading hand 
4249
 
            is higher than lho played card, playing as low as 
4250
 
            possible will give the cheapest win */
4251
 
 
4252
 
        else if ((ll > bitMapRank[posPoint->move[depth+1].rank])&&
4253
 
          (posPoint->rankInSuit[first][leadSuit] > ll))
4254
 
              weight=37/*40*/+rRank;
4255
 
 
4256
 
          /* If rho has a card in the leading suit that
4257
 
             is higher than the trick leading card but lower
4258
 
             than the highest rank of the leading hand, then
4259
 
             lho playing the lowest card will be the cheapest
4260
 
             win */
4261
 
 
4262
 
        else if (mp->rank > posPoint->move[depth+1].rank) {
4263
 
          if (bitMapRank[mp->rank] < ll) 
4264
 
            weight=75-(mp->rank);  /* If played card is lower than any of the cards of
4265
 
                                        rho, it will be the cheapest win */             
4266
 
          else if (bitMapRank[mp->rank] > kk)
4267
 
            weight=70-(mp->rank);  /* If played card is higher than any cards at partner
4268
 
                                    of the leading hand, rho can play low, under the
4269
 
                                    condition that he has a lower card than lho played */    
4270
 
          else {
4271
 
            if (mp->sequence)
4272
 
              weight=62/*63*//*60*/-(mp->rank);   
4273
 
            else
4274
 
              weight=48/*45*/-(mp->rank);  
4275
 
          }
4276
 
        } 
4277
 
        else if (posPoint->length[rho[first]][leadSuit]>0) {
4278
 
          if (mp->sequence)
4279
 
            weight=47/*50*/-(mp->rank);  /* Playing a card in a sequence may promote a winner */
4280
 
                                                                                                /* Insensistive */
4281
 
          else
4282
 
            weight=45-(mp->rank);       
4283
 
        }
4284
 
        else
4285
 
          weight=43/*45*/-(mp->rank);
4286
 
      }
4287
 
      else {
4288
 
        if (!notVoidInSuit) { 
4289
 
          suitCount=posPoint->length[q][suit];
4290
 
          suitAdd=(suitCount<<6)/(33/*36*/);
4291
 
        
4292
 
          /* Discourage suit discard if 2nd highest card becomes singleton. */
4293
 
 
4294
 
          if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
4295
 
            suitAdd-=(4/*2*/);
4296
 
  
4297
 
          if (suit==trump) {
4298
 
            weight=16/*15*/-(mp->rank)+suitAdd;  /* Ruffing is preferred, makes the trick
4299
 
                                                costly for the opponents */
4300
 
          }
4301
 
          else
4302
 
            weight=-6-(mp->rank)+suitAdd;
4303
 
        }
4304
 
        else if ((k > bitMapRank[mp->rank])||
4305
 
          (l > bitMapRank[mp->rank]))
4306
 
          weight=-7/*-9*/+rRank;
4307
 
 
4308
 
          /* If lowest rank for either partner to leading hand 
4309
 
          or rho is higher than played card for lho,
4310
 
          lho should play as low card as possible */
4311
 
                        
4312
 
        else if (mp->rank > posPoint->move[depth+1].rank) {               
4313
 
          if (mp->sequence) 
4314
 
            weight=19/*19*/-(mp->rank); 
4315
 
          else 
4316
 
            weight=10-(mp->rank);
4317
 
        }          
4318
 
        else
4319
 
          weight=-17+rRank;
4320
 
      }
4321
 
      break;
4322
 
 
4323
 
    case 2:
4324
 
            
4325
 
      leadSuit=posPoint->move[depth+2].suit;
4326
 
      if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId)) {
4327
 
        if (suit==leadSuit) {
4328
 
          if (leadSuit!=trump) {
4329
 
            if (((posPoint->length[rho[first]][suit]!=0)||
4330
 
                (posPoint->length[rho[first]][trump]==0))&&
4331
 
                  (bitMapRank[mp->rank] >
4332
 
                   posPoint->rankInSuit[rho[first]][suit]))
4333
 
              winMove=TRUE;
4334
 
          }     
4335
 
          else if (bitMapRank[mp->rank] >
4336
 
            posPoint->rankInSuit[rho[first]][suit])
4337
 
            winMove=TRUE;
4338
 
        }
4339
 
        else {  /* Suit is trump */
4340
 
          if (posPoint->length[rho[first]][leadSuit]==0) {
4341
 
            if (bitMapRank[mp->rank] >
4342
 
                  posPoint->rankInSuit[rho[first]][trump])
4343
 
              winMove=TRUE;
4344
 
          }
4345
 
          else
4346
 
            winMove=TRUE;
4347
 
        }
4348
 
      } 
4349
 
      else if (posPoint->high[depth+1]==first) {
4350
 
        if (posPoint->length[rho[first]][leadSuit]!=0) {
4351
 
          if (posPoint->rankInSuit[rho[first]][leadSuit]
4352
 
                 < bitMapRank[posPoint->move[depth+2].rank])    
4353
 
            winMove=TRUE;
4354
 
        }
4355
 
        else if (leadSuit==trump)
4356
 
          winMove=TRUE;
4357
 
        else if ((leadSuit!=trump) &&
4358
 
            (posPoint->length[rho[first]][trump]==0))
4359
 
          winMove=TRUE;
4360
 
      }
4361
 
      
4362
 
      if (winMove) {
4363
 
        if (!notVoidInSuit) {
4364
 
          suitCount=posPoint->length[q][suit];
4365
 
          suitAdd=(suitCount<<6)/(48/*36*/);
4366
 
 
4367
 
          /* Discourage suit discard if 2nd highest card becomes singleton. */ 
4368
 
 
4369
 
          if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
4370
 
            suitAdd-=(3/*2*/);
4371
 
        
4372
 
          if (posPoint->high[depth+1]==first) {
4373
 
            if (suit==trump) 
4374
 
              weight=30-(mp->rank)+suitAdd;  /* Ruffs partner's winner */  
4375
 
            else 
4376
 
              weight=60-(mp->rank)+suitAdd;  
4377
 
          } 
4378
 
          else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId))
4379
 
 
4380
 
             /* Own hand on top by ruffing */
4381
 
 
4382
 
            weight=70-(mp->rank)+suitAdd;  
4383
 
        }
4384
 
        else 
4385
 
          weight=60-(mp->rank); 
4386
 
      }
4387
 
      else {
4388
 
        if (!notVoidInSuit) {
4389
 
          suitCount=posPoint->length[q][suit];
4390
 
          suitAdd=(suitCount<<6)/36;
4391
 
 
4392
 
          /* Discourage suit discard if 2nd highest card becomes singleton. */
4393
 
 
4394
 
          if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
4395
 
            suitAdd-=(4/*2*/);  
4396
 
          
4397
 
          if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId))
4398
 
 
4399
 
             /* Own hand on top by ruffing */
4400
 
 
4401
 
            weight=40-(mp->rank)+suitAdd;  
4402
 
          else if (suit==trump)
4403
 
 
4404
 
            /* Discard a trump but still losing */
4405
 
 
4406
 
            weight=-/*33*/36+rRank+suitAdd;
4407
 
          else
4408
 
            weight=-(mp->rank)+suitAdd;
4409
 
        }
4410
 
        else {
4411
 
          k=posPoint->rankInSuit[rho[first]][suit];
4412
 
          if ((k & (-k)) > bitMapRank[mp->rank])
4413
 
 
4414
 
            /* If least bit map rank of RHO to lead hand is higher than bit map rank
4415
 
                of current card move. */
4416
 
 
4417
 
            weight=-(mp->rank);
4418
 
 
4419
 
          else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId)) {
4420
 
 
4421
 
            /* If current card move is highest so far. */
4422
 
 
4423
 
            if (mp->rank==posPoint->secondBest[leadSuit].rank)
4424
 
              weight=25;                
4425
 
            else if (mp->sequence)
4426
 
              weight=21/*20*/-(mp->rank);
4427
 
            else
4428
 
              weight=10-(mp->rank);
4429
 
          }
4430
 
          else  
4431
 
            weight=-10-(mp->rank);  
4432
 
        } 
4433
 
      }
4434
 
            
4435
 
      break;
4436
 
 
4437
 
    case 3:
4438
 
      if (!notVoidInSuit) {
4439
 
        suitCount=posPoint->length[q][suit];
4440
 
        suitAdd=(suitCount<<6)/(24/*36*/);
4441
 
        if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
4442
 
          suitAdd-=(2/*0*//*2*/);
4443
 
 
4444
 
        if ((posPoint->high[depth+1])==lho[first]) {
4445
 
 
4446
 
          /* If the current winning move is given by the partner */
4447
 
 
4448
 
          if (suit==trump)
4449
 
 
4450
 
            /* Ruffing partners winner? */
4451
 
 
4452
 
            weight=2/*17*/-(mp->rank)+suitAdd;
4453
 
          else 
4454
 
            weight=25-(mp->rank)+suitAdd;
4455
 
        }
4456
 
        else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId)) 
4457
 
 
4458
 
          /* Own hand ruffs */
4459
 
 
4460
 
          weight=33/*27*/+rRank+suitAdd;                        
4461
 
        else if (suit==trump) 
4462
 
          weight=-13+rRank;                                     
4463
 
        else 
4464
 
          weight=14-(mp->rank)+suitAdd;  
4465
 
      }
4466
 
      else if ((posPoint->high[depth+1])==(lho[first])) {
4467
 
 
4468
 
        /* If the current winning move is given by the partner */
4469
 
 
4470
 
        if (suit==trump)
4471
 
 
4472
 
        /* Ruffs partners winner */
4473
 
 
4474
 
          weight=11+rRank;                                      
4475
 
        else 
4476
 
          weight=17+rRank;
4477
 
      }
4478
 
      else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId))
4479
 
 
4480
 
        /* If present move is superior to current winning move and the
4481
 
        current winning move is not given by the partner */
4482
 
 
4483
 
        weight=22+rRank;                
4484
 
      else {
4485
 
 
4486
 
        /* If present move is not superior to current winning move and the
4487
 
        current winning move is not given by the partner */
4488
 
 
4489
 
        if (suit==trump)
4490
 
 
4491
 
          /* Ruffs but still loses */
4492
 
 
4493
 
          weight=-13+rRank;                     
4494
 
        else 
4495
 
          weight=1+rRank;                       
4496
 
      }
4497
 
  }
4498
 
  return weight;
4499
 
}
4500
 
 
4501
 
 
4502
 
/* Shell-1 */
4503
 
/* K&R page 62: */
4504
 
/*void shellSort(int n, int depth) {
4505
 
  int gap, i, j;
4506
 
  struct moveType temp;
4507
 
 
4508
 
  if (n==2) {
4509
 
    if (movePly[depth].move[0].weight<movePly[depth].move[1].weight) {
4510
 
      temp=movePly[depth].move[0];
4511
 
      movePly[depth].move[0]=movePly[depth].move[1];
4512
 
      movePly[depth].move[1]=temp;
4513
 
      return;
4514
 
    }
4515
 
    else
4516
 
      return;
4517
 
  }
4518
 
  for (gap=n>>1; gap>0; gap>>=1)
4519
 
    for (i=gap; i<n; i++)
4520
 
      for (j=i-gap; j>=0 && movePly[depth].move[j].weight<
4521
 
         movePly[depth].move[j+gap].weight; j-=gap) {
4522
 
        temp=movePly[depth].move[j];
4523
 
        movePly[depth].move[j]=movePly[depth].move[j+gap];
4524
 
        movePly[depth].move[j+gap]=temp;
4525
 
      }
4526
 
} */
4527
 
 
4528
 
/* Shell-2 */
4529
 
/*void shellSort(int n, int depth)
4530
 
{
4531
 
  int i, j, increment;
4532
 
  struct moveType temp;
4533
 
 
4534
 
  if (n==2) {
4535
 
    if (movePly[depth].move[0].weight<movePly[depth].move[1].weight) {
4536
 
      temp=movePly[depth].move[0];
4537
 
      movePly[depth].move[0]=movePly[depth].move[1];
4538
 
      movePly[depth].move[1]=temp;
4539
 
      return;
4540
 
    }
4541
 
    else
4542
 
      return;
4543
 
  }
4544
 
  increment = 3;
4545
 
  while (increment > 0)
4546
 
  {
4547
 
    for (i=0; i < n; i++)
4548
 
    {
4549
 
      j = i;
4550
 
      temp = movePly[depth].move[i];
4551
 
      while ((j >= increment) && (movePly[depth].move[j-increment].weight < temp.weight))
4552
 
      {
4553
 
        movePly[depth].move[j] = movePly[depth].move[j - increment];
4554
 
        j = j - increment;
4555
 
      }
4556
 
      movePly[depth].move[j] = temp;
4557
 
    }
4558
 
    if ((increment>>1) != 0)
4559
 
      increment>>=1;
4560
 
    else if (increment == 1)
4561
 
      increment = 0;
4562
 
    else
4563
 
      increment = 1;
4564
 
  }
4565
 
} */
4566
 
 
4567
 
 
4568
 
/* Insert-1 */
4569
 
/*void InsertSort(int n, int depth, struct movePlyType *mply, int thrId) {
4570
 
  int i, j;
4571
 
  struct moveType a, temp;
4572
 
 
4573
 
  if (n==2) {
4574
 
    if (mply->move[0].weight<mply->move[1].weight) {
4575
 
      temp=mply->move[0];
4576
 
      mply->move[0]=mply->move[1];
4577
 
      mply->move[1]=temp;
4578
 
      return;
4579
 
    }
4580
 
    else
4581
 
      return;
4582
 
  }
4583
 
 
4584
 
  a=mply->move[0];
4585
 
  for (i=1; i<=n-1; i++)
4586
 
    if (mply->move[i].weight>a.weight) {
4587
 
      temp=a;
4588
 
      a=mply->move[i];
4589
 
      mply->move[i]=temp;
4590
 
    }
4591
 
  mply->move[0]=a;
4592
 
  for (i=2; i<=n-1; i++) {
4593
 
    j=i;
4594
 
    a=mply->move[i];
4595
 
    while (a.weight>mply->move[j-1].weight) {
4596
 
      mply->move[j]=mply->move[j-1];
4597
 
      j--;
4598
 
    }
4599
 
    mply->move[j]=a;
4600
 
  }
4601
 
} */
4602
 
 
4603
 
 
4604
 
/* Insert-2 */
4605
 
/*void InsertSort(int n, int depth) {
4606
 
  int i, j;
4607
 
  struct moveType a;
4608
 
 
4609
 
  if (n==2) {
4610
 
    if (movePly[depth].move[0].weight<movePly[depth].move[1].weight) {
4611
 
      a=movePly[depth].move[0];
4612
 
      movePly[depth].move[0]=movePly[depth].move[1];
4613
 
      movePly[depth].move[1]=a;
4614
 
      return;
4615
 
    }
4616
 
    else
4617
 
      return;
4618
 
  }
4619
 
  for (j=1; j<=n-1; j++) {
4620
 
    a=movePly[depth].move[j];
4621
 
    i=j-1;
4622
 
    while ((i>=0)&&(movePly[depth].move[i].weight<a.weight)) {
4623
 
      movePly[depth].move[i+1]=movePly[depth].move[i];
4624
 
      i--;
4625
 
    }
4626
 
    movePly[depth].move[i+1]=a;
4627
 
  }
4628
 
}  */
4629
 
 
4630
 
void MergeSort(int n, struct moveType *a) {
4631
 
 
4632
 
  switch (n) {
4633
 
  case 12:
4634
 
        CMP_SWAP(0, 1); CMP_SWAP(2, 3); CMP_SWAP(4, 5); CMP_SWAP(6, 7); CMP_SWAP(8, 9); CMP_SWAP(10, 11);
4635
 
        CMP_SWAP(1, 3); CMP_SWAP(5, 7); CMP_SWAP(9, 11);
4636
 
        CMP_SWAP(0, 2); CMP_SWAP(4, 6); CMP_SWAP(8, 10);
4637
 
        CMP_SWAP(1, 2); CMP_SWAP(5, 6); CMP_SWAP(9, 10);
4638
 
        CMP_SWAP(1, 5); CMP_SWAP(6, 10);
4639
 
        CMP_SWAP(5, 9);
4640
 
        CMP_SWAP(2, 6);
4641
 
        CMP_SWAP(1, 5); CMP_SWAP(6, 10);
4642
 
        CMP_SWAP(0, 4); CMP_SWAP(7, 11);
4643
 
        CMP_SWAP(3, 7);
4644
 
        CMP_SWAP(4, 8);
4645
 
        CMP_SWAP(0, 4); CMP_SWAP(7, 11);
4646
 
        CMP_SWAP(1, 4); CMP_SWAP(7, 10);
4647
 
        CMP_SWAP(3, 8);
4648
 
        CMP_SWAP(2, 3); CMP_SWAP(8, 9);
4649
 
        CMP_SWAP(2, 4); CMP_SWAP(7, 9);
4650
 
        CMP_SWAP(3, 5); CMP_SWAP(6, 8);
4651
 
        CMP_SWAP(3, 4); CMP_SWAP(5, 6); CMP_SWAP(7, 8);
4652
 
        break;
4653
 
  case 11:
4654
 
        CMP_SWAP(0, 1); CMP_SWAP(2, 3); CMP_SWAP(4, 5); CMP_SWAP(6, 7); CMP_SWAP(8, 9);
4655
 
        CMP_SWAP(1, 3); CMP_SWAP(5, 7);
4656
 
        CMP_SWAP(0, 2); CMP_SWAP(4, 6); CMP_SWAP(8, 10);
4657
 
        CMP_SWAP(1, 2); CMP_SWAP(5, 6); CMP_SWAP(9, 10);
4658
 
        CMP_SWAP(1, 5); CMP_SWAP(6, 10);
4659
 
        CMP_SWAP(5, 9);
4660
 
        CMP_SWAP(2, 6);
4661
 
        CMP_SWAP(1, 5); CMP_SWAP(6, 10);
4662
 
        CMP_SWAP(0, 4);
4663
 
        CMP_SWAP(3, 7);
4664
 
        CMP_SWAP(4, 8);
4665
 
        CMP_SWAP(0, 4);
4666
 
        CMP_SWAP(1, 4); CMP_SWAP(7, 10);
4667
 
        CMP_SWAP(3, 8);
4668
 
        CMP_SWAP(2, 3); CMP_SWAP(8, 9);
4669
 
        CMP_SWAP(2, 4); CMP_SWAP(7, 9);
4670
 
        CMP_SWAP(3, 5); CMP_SWAP(6, 8);
4671
 
        CMP_SWAP(3, 4); CMP_SWAP(5, 6); CMP_SWAP(7, 8);
4672
 
        break;
4673
 
  case 10:
4674
 
        CMP_SWAP(1, 8);
4675
 
        CMP_SWAP(0, 4); CMP_SWAP(5, 9);
4676
 
        CMP_SWAP(2, 6);
4677
 
        CMP_SWAP(3, 7);
4678
 
        CMP_SWAP(0, 3); CMP_SWAP(6, 9);
4679
 
        CMP_SWAP(2, 5);
4680
 
        CMP_SWAP(0, 1); CMP_SWAP(3, 6); CMP_SWAP(8, 9);
4681
 
        CMP_SWAP(4, 7);
4682
 
        CMP_SWAP(0, 2); CMP_SWAP(4, 8);
4683
 
        CMP_SWAP(1, 5); CMP_SWAP(7, 9);
4684
 
        CMP_SWAP(1, 2); CMP_SWAP(3, 4); CMP_SWAP(5, 6); CMP_SWAP(7, 8);
4685
 
        CMP_SWAP(1, 3); CMP_SWAP(6, 8);
4686
 
        CMP_SWAP(2, 4); CMP_SWAP(5, 7);
4687
 
        CMP_SWAP(2, 3); CMP_SWAP(6, 7);
4688
 
        CMP_SWAP(3, 5);
4689
 
        CMP_SWAP(4, 6);
4690
 
        CMP_SWAP(4, 5);
4691
 
        break;
4692
 
  case 9:
4693
 
        CMP_SWAP(0, 1); CMP_SWAP(3, 4); CMP_SWAP(6, 7);
4694
 
        CMP_SWAP(1, 2); CMP_SWAP(4, 5); CMP_SWAP(7, 8);
4695
 
        CMP_SWAP(0, 1); CMP_SWAP(3, 4); CMP_SWAP(6, 7);
4696
 
        CMP_SWAP(0, 3);
4697
 
        CMP_SWAP(3, 6);
4698
 
        CMP_SWAP(0, 3);
4699
 
        CMP_SWAP(1, 4);
4700
 
        CMP_SWAP(4, 7);
4701
 
        CMP_SWAP(1, 4);
4702
 
        CMP_SWAP(2, 5);
4703
 
        CMP_SWAP(5, 8);
4704
 
        CMP_SWAP(2, 5);
4705
 
        CMP_SWAP(1, 3); CMP_SWAP(5, 7);
4706
 
        CMP_SWAP(2, 6);
4707
 
        CMP_SWAP(4, 6);
4708
 
        CMP_SWAP(2, 4);
4709
 
        CMP_SWAP(2, 3); CMP_SWAP(5, 6);
4710
 
        break;
4711
 
  case 8:
4712
 
        CMP_SWAP(0, 1); CMP_SWAP(2, 3); CMP_SWAP(4, 5); CMP_SWAP(6, 7);
4713
 
        CMP_SWAP(0, 2); CMP_SWAP(4, 6); CMP_SWAP(1, 3); CMP_SWAP(5, 7);
4714
 
        CMP_SWAP(1, 2); CMP_SWAP(5, 6); CMP_SWAP(0, 4); CMP_SWAP(1, 5);
4715
 
        CMP_SWAP(2, 6); CMP_SWAP(3, 7); CMP_SWAP(2, 4); CMP_SWAP(3, 5);
4716
 
        CMP_SWAP(1, 2); CMP_SWAP(3, 4); CMP_SWAP(5, 6);
4717
 
        break;
4718
 
  case 7:
4719
 
        CMP_SWAP(0, 1); CMP_SWAP(2, 3); CMP_SWAP(4, 5);
4720
 
        CMP_SWAP(0, 2); CMP_SWAP(4, 6);
4721
 
        CMP_SWAP(1, 3);
4722
 
        CMP_SWAP(1, 2); CMP_SWAP(5, 6);
4723
 
        CMP_SWAP(0, 4); CMP_SWAP(1, 5); CMP_SWAP(2, 6);
4724
 
        CMP_SWAP(2, 4); CMP_SWAP(3, 5);
4725
 
        CMP_SWAP(1, 2); CMP_SWAP(3, 4); CMP_SWAP(5, 6);
4726
 
        break;
4727
 
  case 6:
4728
 
        CMP_SWAP(0, 1); CMP_SWAP(2, 3); CMP_SWAP(4, 5);
4729
 
        CMP_SWAP(0, 2);
4730
 
        CMP_SWAP(1, 3);
4731
 
        CMP_SWAP(1, 2);
4732
 
        CMP_SWAP(0, 4); CMP_SWAP(1, 5);
4733
 
        CMP_SWAP(2, 4); CMP_SWAP(3, 5);
4734
 
        CMP_SWAP(1, 2); CMP_SWAP(3, 4);
4735
 
        break;
4736
 
  case 5:
4737
 
        CMP_SWAP(0, 1); CMP_SWAP(2, 3);
4738
 
        CMP_SWAP(0, 2);
4739
 
        CMP_SWAP(1, 3);
4740
 
        CMP_SWAP(1, 2);
4741
 
        CMP_SWAP(0, 4);
4742
 
        CMP_SWAP(2, 4);
4743
 
        CMP_SWAP(1, 2); CMP_SWAP(3, 4);
4744
 
        break;
4745
 
  case 4:
4746
 
        CMP_SWAP(0, 1); CMP_SWAP(2, 3);
4747
 
        CMP_SWAP(0, 2);
4748
 
        CMP_SWAP(1, 3);
4749
 
        CMP_SWAP(1, 2);
4750
 
        break;
4751
 
  case 3:
4752
 
        CMP_SWAP(0, 1);
4753
 
        CMP_SWAP(0, 2);
4754
 
        CMP_SWAP(1, 2);
4755
 
        break;
4756
 
  case 2:
4757
 
        CMP_SWAP(0, 1);
4758
 
        break;
4759
 
  default:
4760
 
    for (int i = 1; i < n; i++)
4761
 
    {
4762
 
        struct moveType tmp = a[i];
4763
 
        int j = i;
4764
 
        for (; j && tmp.weight > a[j - 1].weight ; --j)
4765
 
            a[j] = a[j - 1];
4766
 
        a[j] = tmp;
4767
 
    }
4768
 
  }
4769
 
 
4770
 
  return;
4771
 
}
4772
 
 
4773
 
 
4774
 
 
4775
 
int AdjustMoveList(int thrId) {
4776
 
  int k, r, n, rank, suit;
4777
 
 
4778
 
  for (k=1; k<=13; k++) {
4779
 
    suit=localVar[thrId].forbiddenMoves[k].suit;
4780
 
    rank=localVar[thrId].forbiddenMoves[k].rank;
4781
 
    for (r=0; r<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; r++) {
4782
 
      if ((suit==localVar[thrId].movePly[localVar[thrId].iniDepth].move[r].suit)&&
4783
 
        (rank!=0)&&(rank==localVar[thrId].movePly[localVar[thrId].iniDepth].move[r].rank)) {
4784
 
        /* For the forbidden move r: */
4785
 
        for (n=r; n<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; n++)
4786
 
          localVar[thrId].movePly[localVar[thrId].iniDepth].move[n]=
4787
 
                  localVar[thrId].movePly[localVar[thrId].iniDepth].move[n+1];
4788
 
        localVar[thrId].movePly[localVar[thrId].iniDepth].last--;
4789
 
      }
4790
 
    }
4791
 
  }
4792
 
  return localVar[thrId].movePly[localVar[thrId].iniDepth].last+1;
4793
 
}
4794
 
 
4795
 
 
4796
 
int InvBitMapRank(unsigned short bitMap) {
4797
 
 
4798
 
  switch (bitMap) {
4799
 
    case 0x1000: return 14;
4800
 
    case 0x0800: return 13;
4801
 
    case 0x0400: return 12;
4802
 
    case 0x0200: return 11;
4803
 
    case 0x0100: return 10;
4804
 
    case 0x0080: return 9;
4805
 
    case 0x0040: return 8;
4806
 
    case 0x0020: return 7;
4807
 
    case 0x0010: return 6;
4808
 
    case 0x0008: return 5;
4809
 
    case 0x0004: return 4;
4810
 
    case 0x0002: return 3;
4811
 
    case 0x0001: return 2;
4812
 
    default: return 0;
4813
 
  }
4814
 
}
4815
 
 
4816
 
int InvWinMask(int mask) {
4817
 
 
4818
 
  switch (mask) {
4819
 
    case 0x01000000: return 1;
4820
 
    case 0x00400000: return 2;
4821
 
    case 0x00100000: return 3;
4822
 
    case 0x00040000: return 4;
4823
 
    case 0x00010000: return 5;
4824
 
    case 0x00004000: return 6;
4825
 
    case 0x00001000: return 7;
4826
 
    case 0x00000400: return 8;
4827
 
    case 0x00000100: return 9;
4828
 
    case 0x00000040: return 10;
4829
 
    case 0x00000010: return 11;
4830
 
    case 0x00000004: return 12;
4831
 
    case 0x00000001: return 13;
4832
 
    default: return 0;
4833
 
  }
4834
 
}
4835
 
 
4836
 
 
4837
 
inline int WinningMove(struct moveType * mvp1, struct moveType * mvp2, int trump, int thrId) {
4838
 
/* Return TRUE if move 1 wins over move 2, with the assumption that
4839
 
move 2 is the presently winning card of the trick */
4840
 
 
4841
 
  if (mvp1->suit==mvp2->suit) {
4842
 
    if ((mvp1->rank)>(mvp2->rank))
4843
 
      return TRUE;
4844
 
    else
4845
 
      return FALSE;
4846
 
  }
4847
 
  else if ((mvp1->suit)==trump)
4848
 
    return TRUE;
4849
 
  else
4850
 
    return FALSE;
4851
 
}
4852
 
 
4853
 
 
4854
 
inline int WinningMoveNT(struct moveType * mvp1, struct moveType * mvp2, int thrId) {
4855
 
/* Return TRUE if move 1 wins over move 2, with the assumption that
4856
 
move 2 is the presently winning card of the trick */
4857
 
 
4858
 
  if (mvp1->suit==mvp2->suit) {
4859
 
    if ((mvp1->rank)>(mvp2->rank))
4860
 
      return TRUE;
4861
 
    else
4862
 
      return FALSE;
4863
 
  }
4864
 
  else
4865
 
    return FALSE;
4866
 
}
4867
 
 
4868
 
 
4869
 
struct nodeCardsType * CheckSOP(struct pos * posPoint, struct nodeCardsType
4870
 
  * nodep, int target, int tricks, int * result, int *value, int thrId) {
4871
 
    /* Check SOP if it matches the
4872
 
    current position. If match, pointer to the SOP node is returned and
4873
 
    result is set to TRUE, otherwise pointer to SOP node is returned
4874
 
    and result set to FALSE. */
4875
 
 
4876
 
  /* 07-04-22 */
4877
 
  if (localVar[thrId].nodeTypeStore[0]==MAXNODE) {
4878
 
    if (nodep->lbound==-1) {  /* This bound values for
4879
 
      this leading hand has not yet been determined */
4880
 
      *result=FALSE;
4881
 
      return nodep;
4882
 
    }
4883
 
    else if ((posPoint->tricksMAX + nodep->lbound)>=target) {
4884
 
      *value=TRUE;
4885
 
      *result=TRUE;
4886
 
      return nodep;
4887
 
    }
4888
 
    else if ((posPoint->tricksMAX + nodep->ubound)<target) {
4889
 
      *value=FALSE;
4890
 
      *result=TRUE;
4891
 
      return nodep;
4892
 
    }
4893
 
  }
4894
 
  else {
4895
 
    if (nodep->ubound==-1) {  /* This bound values for
4896
 
      this leading hand has not yet been determined */
4897
 
      *result=FALSE;
4898
 
      return nodep;
4899
 
    }
4900
 
    else if ((posPoint->tricksMAX + (tricks + 1 - nodep->ubound))>=target) {
4901
 
      *value=TRUE;
4902
 
      *result=TRUE;
4903
 
      return nodep;
4904
 
    }
4905
 
    else if ((posPoint->tricksMAX + (tricks + 1 - nodep->lbound))<target) {
4906
 
      *value=FALSE;
4907
 
      *result=TRUE;
4908
 
      return nodep;
4909
 
    }
4910
 
  }
4911
 
 
4912
 
  *result=FALSE;
4913
 
  return nodep;          /* No matching node was found */
4914
 
}
4915
 
 
4916
 
 
4917
 
struct nodeCardsType * UpdateSOP(struct pos * posPoint, struct nodeCardsType
4918
 
  * nodep) {
4919
 
    /* Update SOP node with new values for upper and lower
4920
 
          bounds. */
4921
 
 
4922
 
  if ((posPoint->lbound > nodep->lbound) ||
4923
 
                (nodep->lbound==-1))
4924
 
    nodep->lbound=posPoint->lbound;
4925
 
  if ((posPoint->ubound < nodep->ubound) ||
4926
 
                (nodep->ubound==-1))
4927
 
    nodep->ubound=posPoint->ubound;
4928
 
 
4929
 
  nodep->bestMoveSuit=posPoint->bestMoveSuit;
4930
 
    nodep->bestMoveRank=posPoint->bestMoveRank;
4931
 
 
4932
 
  return nodep;
4933
 
}
4934
 
 
4935
 
 
4936
 
struct nodeCardsType * FindSOP(struct pos * posPoint,
4937
 
  struct winCardType * nodeP, int firstHand,
4938
 
        int target, int tricks, int * valp, int thrId) {
4939
 
  struct nodeCardsType * sopP;
4940
 
  struct winCardType * np;
4941
 
  int s, res;
4942
 
 
4943
 
  np=nodeP; s=0;
4944
 
  while ((np!=NULL)&&(s<4)) {
4945
 
    if ((np->winMask & posPoint->orderSet[s])==
4946
 
       np->orderSet)  {
4947
 
      /* Winning rank set fits position */
4948
 
      if (s==3) {
4949
 
        sopP=CheckSOP(posPoint, np->first, target, tricks, &res, valp, thrId);
4950
 
        if (res) {
4951
 
          return sopP;
4952
 
        }
4953
 
        else {
4954
 
          if (np->next!=NULL) {
4955
 
            np=np->next;
4956
 
          }
4957
 
          else {
4958
 
            np=np->prevWin;
4959
 
            s--;
4960
 
            if (np==NULL)
4961
 
              return NULL;
4962
 
            while (np->next==NULL) {
4963
 
              np=np->prevWin;
4964
 
              s--;
4965
 
              if (np==NULL)  /* Previous node is header node? */
4966
 
                                return NULL;
4967
 
            }
4968
 
            np=np->next;
4969
 
          }
4970
 
        }
4971
 
      }
4972
 
      else if (s<4) {
4973
 
        np=np->nextWin;
4974
 
        s++;
4975
 
      }
4976
 
    }
4977
 
    else {
4978
 
      if (np->next!=NULL) {
4979
 
        np=np->next;
4980
 
      }
4981
 
      else {
4982
 
        np=np->prevWin;
4983
 
        s--;
4984
 
        if (np==NULL)
4985
 
          return NULL;
4986
 
        while (np->next==NULL) {
4987
 
          np=np->prevWin;
4988
 
          s--;
4989
 
          if (np==NULL)  /* Previous node is header node? */
4990
 
            return NULL;
4991
 
        }
4992
 
        np=np->next;
4993
 
      }
4994
 
    }
4995
 
  }
4996
 
  return NULL;
4997
 
}
4998
 
 
4999
 
 
5000
 
struct nodeCardsType * BuildPath(struct pos * posPoint,
5001
 
  struct posSearchType *nodep, int * result, int thrId) {
5002
 
  /* If result is TRUE, a new SOP has been created and BuildPath returns a
5003
 
  pointer to it. If result is FALSE, an existing SOP is used and BuildPath
5004
 
  returns a pointer to the SOP */
5005
 
 
5006
 
  int found, suit;
5007
 
  struct winCardType * np, * p2, /* * sp2,*/ * nprev, * fnp, *pnp;
5008
 
  struct winCardType temp;
5009
 
  struct nodeCardsType * sopP=0, * p/*, * sp*/;
5010
 
 
5011
 
  np=nodep->posSearchPoint;
5012
 
  nprev=NULL;
5013
 
  suit=0;
5014
 
 
5015
 
  /* If winning node has a card that equals the next winning card deduced
5016
 
  from the position, then there already exists a (partial) path */
5017
 
 
5018
 
  if (np==NULL) {   /* There is no winning list created yet */
5019
 
   /* Create winning nodes */
5020
 
    p2=&localVar[thrId].winCards[localVar[thrId].winSetSize];
5021
 
    AddWinSet(thrId);
5022
 
    p2->next=NULL;
5023
 
    p2->nextWin=NULL;
5024
 
    p2->prevWin=NULL;
5025
 
    nodep->posSearchPoint=p2;
5026
 
    p2->winMask=posPoint->winMask[suit];
5027
 
    p2->orderSet=posPoint->winOrderSet[suit];
5028
 
    p2->first=NULL;
5029
 
    np=p2;           /* Latest winning node */
5030
 
    suit++;
5031
 
    while (suit<4) {
5032
 
      p2=&localVar[thrId].winCards[localVar[thrId].winSetSize];
5033
 
      AddWinSet(thrId);
5034
 
      np->nextWin=p2;
5035
 
      p2->prevWin=np;
5036
 
      p2->next=NULL;
5037
 
      p2->nextWin=NULL;
5038
 
      p2->winMask=posPoint->winMask[suit];
5039
 
      p2->orderSet=posPoint->winOrderSet[suit];
5040
 
      p2->first=NULL;
5041
 
      np=p2;         /* Latest winning node */
5042
 
      suit++;
5043
 
    }
5044
 
    p=&localVar[thrId].nodeCards[localVar[thrId].nodeSetSize];
5045
 
    AddNodeSet(thrId);
5046
 
    np->first=p;
5047
 
    *result=TRUE;
5048
 
    return p;
5049
 
  }
5050
 
  else {   /* Winning list exists */
5051
 
    while (1) {   /* Find all winning nodes that correspond to current
5052
 
                position */
5053
 
      found=FALSE;
5054
 
      while (1) {    /* Find node amongst alternatives */
5055
 
        if ((np->winMask==posPoint->winMask[suit])&&
5056
 
           (np->orderSet==posPoint->winOrderSet[suit])) {
5057
 
           /* Part of path found */
5058
 
          found=TRUE;
5059
 
          nprev=np;
5060
 
          break;
5061
 
        }
5062
 
        if (np->next!=NULL)
5063
 
          np=np->next;
5064
 
        else
5065
 
          break;
5066
 
      }
5067
 
      if (found) {
5068
 
        suit++;
5069
 
        if (suit>3) {
5070
 
          sopP=UpdateSOP(posPoint, np->first);
5071
 
 
5072
 
          if (np->prevWin!=NULL) {
5073
 
            pnp=np->prevWin;
5074
 
            fnp=pnp->nextWin;
5075
 
          }
5076
 
          else
5077
 
            fnp=nodep->posSearchPoint;
5078
 
 
5079
 
          temp.orderSet=np->orderSet;
5080
 
          temp.winMask=np->winMask;
5081
 
          temp.first=np->first;
5082
 
          temp.nextWin=np->nextWin;
5083
 
          np->orderSet=fnp->orderSet;
5084
 
          np->winMask=fnp->winMask;
5085
 
          np->first=fnp->first;
5086
 
          np->nextWin=fnp->nextWin;
5087
 
          fnp->orderSet=temp.orderSet;
5088
 
          fnp->winMask=temp.winMask;
5089
 
          fnp->first=temp.first;
5090
 
          fnp->nextWin=temp.nextWin;
5091
 
 
5092
 
          *result=FALSE;
5093
 
          return sopP;
5094
 
        }
5095
 
        else {
5096
 
          np=np->nextWin;       /* Find next winning node  */
5097
 
          continue;
5098
 
        }
5099
 
      }
5100
 
      else
5101
 
        break;                    /* Node was not found */
5102
 
    }               /* End outer while */
5103
 
 
5104
 
    /* Create additional node, coupled to existing node(s) */
5105
 
    p2=&localVar[thrId].winCards[localVar[thrId].winSetSize];
5106
 
    AddWinSet(thrId);
5107
 
    p2->prevWin=nprev;
5108
 
    if (nprev!=NULL) {
5109
 
      p2->next=nprev->nextWin;
5110
 
      nprev->nextWin=p2;
5111
 
    }
5112
 
    else {
5113
 
      p2->next=nodep->posSearchPoint;
5114
 
      nodep->posSearchPoint=p2;
5115
 
    }
5116
 
    p2->nextWin=NULL;
5117
 
    p2->winMask=posPoint->winMask[suit];
5118
 
    p2->orderSet=posPoint->winOrderSet[suit];
5119
 
    p2->first=NULL;
5120
 
    np=p2;          /* Latest winning node */
5121
 
    suit++;
5122
 
 
5123
 
    /* Rest of path must be created */
5124
 
    while (suit<4) {
5125
 
      p2=&localVar[thrId].winCards[localVar[thrId].winSetSize];
5126
 
      AddWinSet(thrId);
5127
 
      np->nextWin=p2;
5128
 
      p2->prevWin=np;
5129
 
      p2->next=NULL;
5130
 
      p2->winMask=posPoint->winMask[suit];
5131
 
      p2->orderSet=posPoint->winOrderSet[suit];
5132
 
      p2->first=NULL;
5133
 
      p2->nextWin=NULL;
5134
 
      np=p2;         /* Latest winning node */
5135
 
      suit++;
5136
 
    }
5137
 
 
5138
 
  /* All winning nodes in SOP have been traversed and new nodes created */
5139
 
    p=&localVar[thrId].nodeCards[localVar[thrId].nodeSetSize];
5140
 
    AddNodeSet(thrId);
5141
 
    np->first=p;
5142
 
    *result=TRUE;
5143
 
    return p;
5144
 
  }
5145
 
}
5146
 
 
5147
 
 
5148
 
struct posSearchType * SearchLenAndInsert(struct posSearchType
5149
 
        * rootp, long long key, int insertNode, int *result, int thrId) {
5150
 
/* Search for node which matches with the suit length combination
5151
 
   given by parameter key. If no such node is found, NULL is
5152
 
  returned if parameter insertNode is FALSE, otherwise a new
5153
 
  node is inserted with suitLengths set to key, the pointer to
5154
 
  this node is returned.
5155
 
  The algorithm used is defined in Knuth "The art of computer
5156
 
  programming", vol.3 "Sorting and searching", 6.2.2 Algorithm T,
5157
 
  page 424. */
5158
 
 
5159
 
  struct posSearchType *np, *p, *sp;
5160
 
 
5161
 
  if (insertNode)
5162
 
    sp=&localVar[thrId].posSearch[localVar[thrId].lenSetSize];
5163
 
 
5164
 
  np=rootp;
5165
 
  while (1) {
5166
 
    if (key==np->suitLengths) {
5167
 
      *result=TRUE;
5168
 
      return np;
5169
 
    }
5170
 
    else if (key < np->suitLengths) {
5171
 
      if (np->left!=NULL)
5172
 
        np=np->left;
5173
 
      else if (insertNode) {
5174
 
        p=sp;
5175
 
        AddLenSet(thrId);
5176
 
        np->left=p;
5177
 
        p->posSearchPoint=NULL;
5178
 
        p->suitLengths=key;
5179
 
        p->left=NULL; p->right=NULL;
5180
 
        *result=TRUE;
5181
 
        return p;
5182
 
      }
5183
 
      else {
5184
 
        *result=FALSE;
5185
 
        return NULL;
5186
 
      }
5187
 
    }
5188
 
    else {      /* key > suitLengths */
5189
 
      if (np->right!=NULL)
5190
 
        np=np->right;
5191
 
      else if (insertNode) {
5192
 
        p=sp;
5193
 
        AddLenSet(thrId);
5194
 
        np->right=p;
5195
 
        p->posSearchPoint=NULL;
5196
 
        p->suitLengths=key;
5197
 
        p->left=NULL; p->right=NULL;
5198
 
        *result=TRUE;
5199
 
        return p;
5200
 
      }
5201
 
      else {
5202
 
        *result=FALSE;
5203
 
        return NULL;
5204
 
      }
5205
 
    }
5206
 
  }
5207
 
}
5208
 
 
5209
 
 
5210
 
 
5211
 
void BuildSOP(struct pos * posPoint, int tricks, int firstHand, int target,
5212
 
  int depth, int scoreFlag, int score, int thrId) {
5213
 
  int ss, hh, res, wm;
5214
 
  unsigned short int w;
5215
 
  unsigned short int temp[4][4];
5216
 
  unsigned short int aggr[4];
5217
 
  struct nodeCardsType * cardsP;
5218
 
  struct posSearchType * np;
5219
 
  long long suitLengths;
5220
 
 
5221
 
#ifdef TTDEBUG
5222
 
  int k, mcurrent, rr;
5223
 
  mcurrent=localVar[thrId].movePly[depth].current;
5224
 
#endif
5225
 
 
5226
 
  for (ss=0; ss<=3; ss++) {
5227
 
    w=posPoint->winRanks[depth][ss];
5228
 
    if (w==0) {
5229
 
      posPoint->winMask[ss]=0;
5230
 
      posPoint->winOrderSet[ss]=0;
5231
 
      posPoint->leastWin[ss]=0;
5232
 
      for (hh=0; hh<=3; hh++)
5233
 
        temp[hh][ss]=0;
5234
 
    }
5235
 
    else {
5236
 
      w=w & (-w);       /* Only lowest win */
5237
 
      for (hh=0; hh<=3; hh++)
5238
 
        temp[hh][ss]=posPoint->rankInSuit[hh][ss] & (-w);
5239
 
 
5240
 
      aggr[ss]=0;
5241
 
      for (hh=0; hh<=3; hh++)
5242
 
        aggr[ss]=aggr[ss] | temp[hh][ss];
5243
 
      posPoint->winMask[ss]=localVar[thrId].rel[aggr[ss]].winMask[ss];
5244
 
      posPoint->winOrderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss];
5245
 
      wm=posPoint->winMask[ss];
5246
 
      wm=wm & (-wm);
5247
 
      posPoint->leastWin[ss]=InvWinMask(wm);
5248
 
    }
5249
 
  }
5250
 
 
5251
 
  /* 07-04-22 */
5252
 
  if (scoreFlag) {
5253
 
    if (localVar[thrId].nodeTypeStore[0]==MAXNODE) {
5254
 
      posPoint->ubound=tricks+1;
5255
 
      posPoint->lbound=target-posPoint->tricksMAX;
5256
 
    }
5257
 
    else {
5258
 
      posPoint->ubound=tricks+1-target+posPoint->tricksMAX;
5259
 
      posPoint->lbound=0;
5260
 
    }
5261
 
  }
5262
 
  else {
5263
 
    if (localVar[thrId].nodeTypeStore[0]==MAXNODE) {
5264
 
      posPoint->ubound=target-posPoint->tricksMAX-1;
5265
 
      posPoint->lbound=0;
5266
 
    }
5267
 
    else {
5268
 
      posPoint->ubound=tricks+1;
5269
 
      posPoint->lbound=tricks+1-target+posPoint->tricksMAX+1;
5270
 
    }
5271
 
  }
5272
 
 
5273
 
  suitLengths=0;
5274
 
  for (ss=0; ss<=2; ss++)
5275
 
    for (hh=0; hh<=3; hh++) {
5276
 
      suitLengths<<=4;
5277
 
      suitLengths|=posPoint->length[hh][ss];
5278
 
    }
5279
 
 
5280
 
  np=SearchLenAndInsert(localVar[thrId].rootnp[tricks][firstHand],
5281
 
         suitLengths, TRUE, &res, thrId);
5282
 
 
5283
 
  cardsP=BuildPath(posPoint, np, &res, thrId);
5284
 
  if (res) {
5285
 
    cardsP->ubound=posPoint->ubound;
5286
 
    cardsP->lbound=posPoint->lbound;
5287
 
    if (((localVar[thrId].nodeTypeStore[firstHand]==MAXNODE)&&(scoreFlag))||
5288
 
        ((localVar[thrId].nodeTypeStore[firstHand]==MINNODE)&&(!scoreFlag))) {
5289
 
      cardsP->bestMoveSuit=localVar[thrId].bestMove[depth].suit;
5290
 
      cardsP->bestMoveRank=localVar[thrId].bestMove[depth].rank;
5291
 
    }
5292
 
    else {
5293
 
      cardsP->bestMoveSuit=0;
5294
 
      cardsP->bestMoveRank=0;
5295
 
    }
5296
 
    posPoint->bestMoveSuit=localVar[thrId].bestMove[depth].suit;
5297
 
    posPoint->bestMoveRank=localVar[thrId].bestMove[depth].rank;
5298
 
    for (ss=0; ss<=3; ss++)
5299
 
      cardsP->leastWin[ss]=posPoint->leastWin[ss];
5300
 
  }
5301
 
 
5302
 
  #ifdef STAT
5303
 
    c9[depth]++;
5304
 
  #endif
5305
 
 
5306
 
  #ifdef TTDEBUG
5307
 
  if ((res) && (ttCollect) && (!suppressTTlog)) {
5308
 
    fprintf(localVar[thrId].fp7, "cardsP=%d\n", (int)cardsP);
5309
 
    fprintf(localVar[thrId].fp7, "nodeSetSize=%d\n", localVar[thrId].nodeSetSize);
5310
 
    fprintf(localVar[thrId].fp7, "ubound=%d\n", cardsP->ubound);
5311
 
    fprintf(localVar[thrId].fp7, "lbound=%d\n", cardsP->lbound);
5312
 
    fprintf(localVar[thrId].fp7, "target=%d\n", target);
5313
 
    fprintf(localVar[thrId].fp7, "first=%c nextFirst=%c\n",
5314
 
      cardHand[posPoint->first[depth]], cardHand[posPoint->first[depth-1]]);
5315
 
    fprintf(localVar[thrId].fp7, "bestMove:  suit=%c rank=%c\n", cardSuit[localVar[thrId].bestMove[depth].suit],
5316
 
      cardRank[localVar[thrId].bestMove[depth].rank]);
5317
 
    fprintf(localVar[thrId].fp7, "\n");
5318
 
    fprintf(localVar[thrId].fp7, "Last trick:\n");
5319
 
    fprintf(localVar[thrId].fp7, "1st hand=%c\n", cardHand[posPoint->first[depth+3]]);
5320
 
    for (k=3; k>=0; k--) {
5321
 
      mcurrent=localVar[thrId].movePly[depth+k+1].current;
5322
 
      fprintf(localVar[thrId].fp7, "suit=%c  rank=%c\n",
5323
 
        cardSuit[localVar[thrId].movePly[depth+k+1].move[mcurrent].suit],
5324
 
        cardRank[localVar[thrId].movePly[depth+k+1].move[mcurrent].rank]);
5325
 
    }
5326
 
    fprintf(localVar[thrId].fp7, "\n");
5327
 
    for (hh=0; hh<=3; hh++) {
5328
 
      fprintf(localVar[thrId].fp7, "hand=%c\n", cardHand[hh]);
5329
 
      for (ss=0; ss<=3; ss++) {
5330
 
        fprintf(localVar[thrId].fp7, "suit=%c", cardSuit[ss]);
5331
 
        for (rr=14; rr>=2; rr--)
5332
 
          if (posPoint->rankInSuit[hh][ss] & bitMapRank[rr])
5333
 
            fprintf(localVar[thrId].fp7, " %c", cardRank[rr]);
5334
 
        fprintf(localVar[thrId].fp7, "\n");
5335
 
      }
5336
 
      fprintf(localVar[thrId].fp7, "\n");
5337
 
    }
5338
 
    fprintf(localVar[thrId].fp7, "\n");
5339
 
  }
5340
 
  #endif
5341
 
}
5342
 
 
5343
 
 
5344
 
int CheckDeal(struct moveType * cardp, int thrId) {
5345
 
  int h, s, k, found;
5346
 
  unsigned short int temp[4][4];
5347
 
 
5348
 
  for (h=0; h<=3; h++)
5349
 
    for (s=0; s<=3; s++)
5350
 
      temp[h][s]=localVar[thrId].game.suit[h][s];
5351
 
 
5352
 
  /* Check that all ranks appear only once within the same suit. */
5353
 
  for (s=0; s<=3; s++)
5354
 
    for (k=2; k<=14; k++) {
5355
 
      found=FALSE;
5356
 
      for (h=0; h<=3; h++) {
5357
 
        if ((temp[h][s] & bitMapRank[k])!=0) {
5358
 
          if (found) {
5359
 
            cardp->suit=s;
5360
 
            cardp->rank=k;
5361
 
            return 1;
5362
 
          }
5363
 
          else
5364
 
            found=TRUE;
5365
 
        }
5366
 
      }
5367
 
    }
5368
 
 
5369
 
  return 0;
5370
 
}
5371
 
 
5372
 
 
5373
 
int NextMove(struct pos *posPoint, int depth, struct movePlyType *mply, int thrId) {
5374
 
  /* Returns TRUE if at least one move remains to be
5375
 
  searched, otherwise FALSE is returned. */
5376
 
  int mcurrent;
5377
 
  unsigned short int lw;
5378
 
  unsigned char suit;
5379
 
  struct moveType currMove;
5380
 
 
5381
 
  mcurrent=mply->current;
5382
 
  currMove=mply->move[mcurrent];
5383
 
 
5384
 
  if (localVar[thrId].lowestWin[depth][currMove.suit]==0) {
5385
 
    /* A small card has not yet been identified for this suit. */
5386
 
    lw=posPoint->winRanks[depth][currMove.suit];
5387
 
    if (lw!=0)
5388
 
      lw=lw & (-lw);  /* LSB */
5389
 
    else
5390
 
      lw=bitMapRank[15];
5391
 
    if (bitMapRank[currMove.rank]<lw) {
5392
 
       /* The current move has a small card. */
5393
 
      localVar[thrId].lowestWin[depth][currMove.suit]=lw;
5394
 
      while (mply->current <= (mply->last-1)) {
5395
 
        mply->current++;
5396
 
        mcurrent=mply->current;
5397
 
        if (bitMapRank[mply->move[mcurrent].rank] >=
5398
 
          localVar[thrId].lowestWin[depth][mply->move[mcurrent].suit])
5399
 
          return TRUE;
5400
 
      }
5401
 
      return FALSE;
5402
 
    }
5403
 
    else {
5404
 
      while (mply->current <= (mply->last-1)) {
5405
 
        mply->current++;
5406
 
        mcurrent=mply->current;
5407
 
        suit=mply->move[mcurrent].suit;
5408
 
        if ((currMove.suit==suit) || (bitMapRank[mply->move[mcurrent].rank] >=
5409
 
                localVar[thrId].lowestWin[depth][suit]))
5410
 
          return TRUE;
5411
 
      }
5412
 
      return FALSE;
5413
 
    }
5414
 
  }
5415
 
  else {
5416
 
    while (mply->current<=(mply->last-1)) {
5417
 
      mply->current++;
5418
 
      mcurrent=mply->current;
5419
 
      if (bitMapRank[mply->move[mcurrent].rank] >=
5420
 
            localVar[thrId].lowestWin[depth][mply->move[mcurrent].suit])
5421
 
        return TRUE;
5422
 
    }
5423
 
    return FALSE;
5424
 
  }
5425
 
}
5426
 
 
5427
 
 
5428
 
int DumpInput(int errCode, struct deal dl, int target,
5429
 
    int solutions, int mode) {
5430
 
 
5431
 
  FILE *fp;
5432
 
  int i, j, k;
5433
 
  unsigned short ranks[4][4];
5434
 
 
5435
 
  fp=fopen("dump.txt", "w");
5436
 
  if (fp==NULL)
5437
 
    return -1;
5438
 
  fprintf(fp, "Error code=%d\n", errCode);
5439
 
  fprintf(fp, "\n");
5440
 
  fprintf(fp, "Deal data:\n");
5441
 
  if (dl.trump!=4)
5442
 
    fprintf(fp, "trump=%c\n", cardSuit[dl.trump]);
5443
 
  else
5444
 
    fprintf(fp, "trump=N\n");
5445
 
  fprintf(fp, "first=%c\n", cardHand[dl.first]);
5446
 
  for (k=0; k<=2; k++)
5447
 
    if (dl.currentTrickRank[k]!=0)
5448
 
      fprintf(fp, "index=%d currentTrickSuit=%c currentTrickRank=%c\n",
5449
 
        k, cardSuit[dl.currentTrickSuit[k]], cardRank[dl.currentTrickRank[k]]);
5450
 
  for (i=0; i<=3; i++)
5451
 
    for (j=0; j<=3; j++) {
5452
 
      fprintf(fp, "index1=%d index2=%d remainCards=%d\n",
5453
 
        i, j, dl.remainCards[i][j]);
5454
 
      ranks[i][j]=dl.remainCards[i][/*3-*/j]>>2;
5455
 
    }
5456
 
  fprintf(fp, "\n");
5457
 
  fprintf(fp, "target=%d\n", target);
5458
 
  fprintf(fp, "solutions=%d\n", solutions);
5459
 
  fprintf(fp, "mode=%d\n", mode);
5460
 
  fprintf(fp, "\n");
5461
 
  PrintDeal(fp, ranks);
5462
 
  fclose(fp);
5463
 
  return 0;
5464
 
}
5465
 
 
5466
 
void PrintDeal(FILE *fp, unsigned short ranks[][4]) {
5467
 
  int i, count, ec[4], trickCount=0, s, r;
5468
 
  for (i=0; i<=3; i++) {
5469
 
    count=counttable[ranks[3][i]];
5470
 
    if (count>5)
5471
 
      ec[i]=TRUE;
5472
 
    else
5473
 
      ec[i]=FALSE;
5474
 
    trickCount=trickCount+count;
5475
 
  }
5476
 
  fprintf(fp, "\n");
5477
 
  for (s=0; s<=3; s++) {
5478
 
    fprintf(fp, "\t%c ", cardSuit[s]);
5479
 
    if (!ranks[0][s])
5480
 
      fprintf(fp, "--");
5481
 
    else {
5482
 
      for (r=14; r>=2; r--)
5483
 
        if ((ranks[0][s] & bitMapRank[r])!=0)
5484
 
          fprintf(fp, "%c", cardRank[r]);
5485
 
    }
5486
 
    fprintf(fp, "\n");
5487
 
  }
5488
 
  for (s=0; s<=3; s++) {
5489
 
    fprintf(fp, "%c ", cardSuit[s]);
5490
 
    if (!ranks[3][s])
5491
 
      fprintf(fp, "--");
5492
 
    else {
5493
 
      for (r=14; r>=2; r--)
5494
 
        if ((ranks[3][s] & bitMapRank[r])!=0)
5495
 
          fprintf(fp, "%c", cardRank[r]);
5496
 
    }
5497
 
    if (ec[s])
5498
 
      fprintf(fp, "\t\%c ", cardSuit[s]);
5499
 
    else
5500
 
      fprintf(fp, "\t\t\%c ", cardSuit[s]);
5501
 
    if (!ranks[1][s])
5502
 
      fprintf(fp, "--");
5503
 
    else {
5504
 
      for (r=14; r>=2; r--)
5505
 
        if ((ranks[1][s] & bitMapRank[r])!=0)
5506
 
            fprintf(fp, "%c", cardRank[r]);
5507
 
    }
5508
 
    fprintf(fp, "\n");
5509
 
  }
5510
 
  for (s=0; s<=3; s++) {
5511
 
    fprintf(fp, "\t%c ", cardSuit[s]);
5512
 
    if (!ranks[2][s])
5513
 
      fprintf(fp, "--");
5514
 
    else {
5515
 
      for (r=14; r>=2; r--)
5516
 
        if ((ranks[2][s] & bitMapRank[r])!=0)
5517
 
          fprintf(fp, "%c", cardRank[r]);
5518
 
    }
5519
 
    fprintf(fp, "\n");
5520
 
  }
5521
 
  fprintf(fp, "\n");
5522
 
  return;
5523
 
}
5524
 
 
5525
 
 
5526
 
 
5527
 
void Wipe(int thrId) {
5528
 
  int k;
5529
 
 
5530
 
  for (k=1; k<=localVar[thrId].wcount; k++) {
5531
 
    if (localVar[thrId].pw[k])
5532
 
      free(localVar[thrId].pw[k]);
5533
 
    localVar[thrId].pw[k]=NULL;
5534
 
  }
5535
 
  for (k=1; k<=localVar[thrId].ncount; k++) {
5536
 
    if (localVar[thrId].pn[k])
5537
 
      free(localVar[thrId].pn[k]);
5538
 
    localVar[thrId].pn[k]=NULL;
5539
 
  }
5540
 
  for (k=1; k<=localVar[thrId].lcount; k++) {
5541
 
    if (localVar[thrId].pl[k])
5542
 
      free(localVar[thrId].pl[k]);
5543
 
    localVar[thrId].pl[k]=NULL;
5544
 
  }
5545
 
 
5546
 
  localVar[thrId].allocmem=localVar[thrId].summem;
5547
 
 
5548
 
  return;
5549
 
}
5550
 
 
5551
 
 
5552
 
void AddWinSet(int thrId) {
5553
 
  if (localVar[thrId].clearTTflag) {
5554
 
    localVar[thrId].windex++;
5555
 
    localVar[thrId].winSetSize=localVar[thrId].windex;
5556
 
    /*localVar[thrId].fp2=fopen("dyn.txt", "a");
5557
 
    fprintf(localVar[thrId].fp2, "windex=%d\n", windex);
5558
 
    fclose(localVar[thrId].fp2);*/
5559
 
    localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex];
5560
 
  }
5561
 
  else if (localVar[thrId].winSetSize>=localVar[thrId].winSetSizeLimit) {
5562
 
    /* The memory chunk for the winCards structure will be exceeded. */
5563
 
    if ((localVar[thrId].allocmem+localVar[thrId].wmem)>localVar[thrId].maxmem) {
5564
 
      /* Already allocated memory plus needed allocation overshot maxmem */
5565
 
      localVar[thrId].windex++;
5566
 
      localVar[thrId].winSetSize=localVar[thrId].windex;
5567
 
      /*localVar[thrId].fp2=fopen("dyn.txt", "a");
5568
 
      fprintf(localVar[thrId].fp2, "windex=%d\n", windex);
5569
 
      fclose(localVar[thrId].fp2);*/
5570
 
      localVar[thrId].clearTTflag=TRUE;
5571
 
      localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex];
5572
 
    }
5573
 
    else {
5574
 
      localVar[thrId].wcount++; localVar[thrId].winSetSizeLimit=WSIZE;
5575
 
      localVar[thrId].pw[localVar[thrId].wcount] =
5576
 
                  (struct winCardType *)calloc(localVar[thrId].winSetSizeLimit+1, sizeof(struct winCardType));
5577
 
      if (localVar[thrId].pw[localVar[thrId].wcount]==NULL) {
5578
 
        localVar[thrId].clearTTflag=TRUE;
5579
 
        localVar[thrId].windex++;
5580
 
        localVar[thrId].winSetSize=localVar[thrId].windex;
5581
 
        localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex];
5582
 
      }
5583
 
      else {
5584
 
        localVar[thrId].allocmem+=(localVar[thrId].winSetSizeLimit+1)*sizeof(struct winCardType);
5585
 
        localVar[thrId].winSetSize=0;
5586
 
        localVar[thrId].winCards=localVar[thrId].pw[localVar[thrId].wcount];
5587
 
      }
5588
 
    }
5589
 
  }
5590
 
  else
5591
 
    localVar[thrId].winSetSize++;
5592
 
  return;
5593
 
}
5594
 
 
5595
 
void AddNodeSet(int thrId) {
5596
 
  if (localVar[thrId].nodeSetSize>=localVar[thrId].nodeSetSizeLimit) {
5597
 
    /* The memory chunk for the nodeCards structure will be exceeded. */
5598
 
    if ((localVar[thrId].allocmem+localVar[thrId].nmem)>localVar[thrId].maxmem) {
5599
 
      /* Already allocated memory plus needed allocation overshot maxmem */
5600
 
      localVar[thrId].clearTTflag=TRUE;
5601
 
    }
5602
 
    else {
5603
 
      localVar[thrId].ncount++; localVar[thrId].nodeSetSizeLimit=NSIZE;
5604
 
      localVar[thrId].pn[localVar[thrId].ncount] = (struct nodeCardsType *)calloc(localVar[thrId].nodeSetSizeLimit+1, sizeof(struct nodeCardsType));
5605
 
      if (localVar[thrId].pn[localVar[thrId].ncount]==NULL) {
5606
 
        localVar[thrId].clearTTflag=TRUE;
5607
 
      }
5608
 
      else {
5609
 
        localVar[thrId].allocmem+=(localVar[thrId].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType);
5610
 
        localVar[thrId].nodeSetSize=0;
5611
 
        localVar[thrId].nodeCards=localVar[thrId].pn[localVar[thrId].ncount];
5612
 
      }
5613
 
    }
5614
 
  }
5615
 
  else
5616
 
    localVar[thrId].nodeSetSize++;
5617
 
  return;
5618
 
}
5619
 
 
5620
 
void AddLenSet(int thrId) {
5621
 
  if (localVar[thrId].lenSetSize>=localVar[thrId].lenSetSizeLimit) {
5622
 
      /* The memory chunk for the posSearchType structure will be exceeded. */
5623
 
    if ((localVar[thrId].allocmem+localVar[thrId].lmem)>localVar[thrId].maxmem) {
5624
 
       /* Already allocated memory plus needed allocation overshot maxmem */
5625
 
      localVar[thrId].clearTTflag=TRUE;
5626
 
    }
5627
 
    else {
5628
 
      localVar[thrId].lcount++; localVar[thrId].lenSetSizeLimit=LSIZE;
5629
 
      localVar[thrId].pl[localVar[thrId].lcount] = (struct posSearchType *)calloc(localVar[thrId].lenSetSizeLimit+1, sizeof(struct posSearchType));
5630
 
      if (localVar[thrId].pl[localVar[thrId].lcount]==NULL) {
5631
 
        localVar[thrId].clearTTflag=TRUE;
5632
 
      }
5633
 
      else {
5634
 
        localVar[thrId].allocmem+=(localVar[thrId].lenSetSizeLimit+1)*sizeof(struct posSearchType);
5635
 
        localVar[thrId].lenSetSize=0;
5636
 
        localVar[thrId].posSearch=localVar[thrId].pl[localVar[thrId].lcount];
5637
 
      }
5638
 
    }
5639
 
  }
5640
 
  else
5641
 
    localVar[thrId].lenSetSize++;
5642
 
  return;
5643
 
}
5644
 
 
5645
 
 
5646
 
 
5647
 
#ifdef TTDEBUG
5648
 
 
5649
 
void ReceiveTTstore(struct pos *posPoint, struct nodeCardsType * cardsP,
5650
 
  int target, int depth, int thrId) {
5651
 
  int tricksLeft, hh, ss, rr;
5652
 
/* Stores current position information and TT position value in table
5653
 
  ttStore with current entry lastTTStore. Also stores corresponding
5654
 
  information in log rectt.txt. */
5655
 
  tricksLeft=0;
5656
 
  for (hh=0; hh<=3; hh++)
5657
 
    for (ss=0; ss<=3; ss++)
5658
 
      tricksLeft+=posPoint->length[hh][ss];
5659
 
  tricksLeft=tricksLeft/4;
5660
 
  ttStore[lastTTstore].tricksLeft=tricksLeft;
5661
 
  ttStore[lastTTstore].cardsP=cardsP;
5662
 
  ttStore[lastTTstore].first=posPoint->first[depth];
5663
 
  if ((localVar[thrId].handToPlay==posPoint->first[depth])||
5664
 
    (localVar[thrId].handToPlay==partner[posPoint->first[depth]])) {
5665
 
    ttStore[lastTTstore].target=target-posPoint->tricksMAX;
5666
 
    ttStore[lastTTstore].ubound=cardsP->ubound;
5667
 
    ttStore[lastTTstore].lbound=cardsP->lbound;
5668
 
  }
5669
 
  else {
5670
 
    ttStore[lastTTstore].target=tricksLeft-
5671
 
      target+posPoint->tricksMAX+1;
5672
 
  }
5673
 
  for (hh=0; hh<=3; hh++)
5674
 
    for (ss=0; ss<=3; ss++)
5675
 
      ttStore[lastTTstore].suit[hh][ss]=
5676
 
        posPoint->rankInSuit[hh][ss];
5677
 
  localVar[thrId].fp11=fopen("rectt.txt", "a");
5678
 
  if (lastTTstore<SEARCHSIZE) {
5679
 
    fprintf(localVar[thrId].fp11, "lastTTstore=%d\n", lastTTstore);
5680
 
    fprintf(localVar[thrId].fp11, "tricksMAX=%d\n", posPoint->tricksMAX);
5681
 
    fprintf(localVar[thrId].fp11, "leftTricks=%d\n",
5682
 
      ttStore[lastTTstore].tricksLeft);
5683
 
    fprintf(localVar[thrId].fp11, "cardsP=%d\n",
5684
 
      ttStore[lastTTstore].cardsP);
5685
 
    fprintf(localVar[thrId].fp11, "ubound=%d\n",
5686
 
      ttStore[lastTTstore].ubound);
5687
 
    fprintf(localVar[thrId].fp11, "lbound=%d\n",
5688
 
      ttStore[lastTTstore].lbound);
5689
 
    fprintf(localVar[thrId].fp11, "first=%c\n",
5690
 
      cardHand[ttStore[lastTTstore].first]);
5691
 
    fprintf(localVar[thrId].fp11, "target=%d\n",
5692
 
      ttStore[lastTTstore].target);
5693
 
    fprintf(localVar[thrId].fp11, "\n");
5694
 
    for (hh=0; hh<=3; hh++) {
5695
 
      fprintf(localVar[thrId].fp11, "hand=%c\n", cardHand[hh]);
5696
 
      for (ss=0; ss<=3; ss++) {
5697
 
        fprintf(localVar[thrId].fp11, "suit=%c", cardSuit[ss]);
5698
 
        for (rr=14; rr>=2; rr--)
5699
 
          if (ttStore[lastTTstore].suit[hh][ss]
5700
 
            & bitMapRank[rr])
5701
 
            fprintf(localVar[thrId].fp11, " %c", cardRank[rr]);
5702
 
         fprintf(localVar[thrId].fp11, "\n");
5703
 
      }
5704
 
      fprintf(localVar[thrId].fp11, "\n");
5705
 
    }
5706
 
  }
5707
 
  fclose(localVar[thrId].fp11);
5708
 
  lastTTstore++;
5709
 
}
5710
 
#endif
5711
 
 
5712
 
#if defined(_WIN32)
5713
 
HANDLE solveAllEvents[MAXNOOFTHREADS];
5714
 
struct paramType param;
5715
 
LONG volatile threadIndex;
5716
 
LONG volatile current;
5717
 
 
5718
 
const long chunk = 4;
5719
 
 
5720
 
DWORD CALLBACK SolveChunkDDtable (void *) {
5721
 
  struct futureTricks fut[MAXNOOFBOARDS];
5722
 
  int thid;
5723
 
  long j;
5724
 
 
5725
 
  thid=InterlockedIncrement(&threadIndex);
5726
 
 
5727
 
  while ((j=InterlockedExchangeAdd(&current, chunk))<param.noOfBoards) {
5728
 
 
5729
 
    for (int k=0; k<chunk && j+k<param.noOfBoards; k++) {
5730
 
      int res=SolveBoard(param.bop->deals[j+k], param.bop->target[j+k],
5731
 
          param.bop->solutions[j+k], param.bop->mode[j+k], 
5732
 
          &fut[j+k], thid);
5733
 
      if (res==1) {
5734
 
        param.solvedp->solvedBoard[j+k]=fut[j+k];
5735
 
        param.error=0;
5736
 
      }
5737
 
      else {
5738
 
        param.error=res;
5739
 
      }
5740
 
    }
5741
 
  }
5742
 
 
5743
 
  if (SetEvent(solveAllEvents[thid])==0) {
5744
 
    int errCode=GetLastError();
5745
 
    return 0;
5746
 
  }
5747
 
 
5748
 
  return 1;
5749
 
 
5750
 
}
5751
 
 
5752
 
int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp) {
5753
 
  int k, errCode;
5754
 
  DWORD res;
5755
 
  DWORD solveAllWaitResult;
5756
 
 
5757
 
  current=0;
5758
 
 
5759
 
  threadIndex=-1;
5760
 
 
5761
 
  if (bop->noOfBoards > MAXNOOFBOARDS)
5762
 
    return -101;
5763
 
 
5764
 
  for (k=0; k<noOfCores; k++) {
5765
 
    solveAllEvents[k]=CreateEvent(NULL, FALSE, FALSE, 0);
5766
 
    if (solveAllEvents[k]==0) {
5767
 
      errCode=GetLastError();
5768
 
      return -102;
5769
 
    }
5770
 
  }
5771
 
 
5772
 
  param.bop=bop; param.solvedp=solvedp; param.noOfBoards=bop->noOfBoards;
5773
 
 
5774
 
  for (k=0; k<MAXNOOFBOARDS; k++)
5775
 
    solvedp->solvedBoard[k].cards=0;
5776
 
 
5777
 
  for (k=0; k<noOfCores; k++) {
5778
 
    res=QueueUserWorkItem(SolveChunkDDtable, NULL, WT_EXECUTELONGFUNCTION);
5779
 
    if (res!=1) {
5780
 
      errCode=GetLastError();
5781
 
      return res;
5782
 
    }
5783
 
  }
5784
 
 
5785
 
  solveAllWaitResult = WaitForMultipleObjects(noOfCores,
5786
 
          solveAllEvents, TRUE, INFINITE);
5787
 
  if (solveAllWaitResult!=WAIT_OBJECT_0) {
5788
 
    errCode=GetLastError();
5789
 
    return -103;
5790
 
  }
5791
 
 
5792
 
  for (k=0; k<noOfCores; k++) {
5793
 
    CloseHandle(solveAllEvents[k]);
5794
 
  }
5795
 
 
5796
 
  /* Calculate number of solved boards. */
5797
 
 
5798
 
  solvedp->noOfBoards=0;
5799
 
  for (k=0; k<MAXNOOFBOARDS; k++) {
5800
 
    if (solvedp->solvedBoard[k].cards!=0)
5801
 
      solvedp->noOfBoards++;
5802
 
  }
5803
 
 
5804
 
  if (param.error==0)
5805
 
    return 1;
5806
 
  else
5807
 
    return param.error;
5808
 
}
5809
 
 
5810
 
DWORD CALLBACK SolveChunk (void *) {
5811
 
  struct futureTricks fut[MAXNOOFBOARDS];
5812
 
  int thid;
5813
 
  long j;
5814
 
 
5815
 
  thid=InterlockedIncrement(&threadIndex);
5816
 
 
5817
 
  while ((j=(InterlockedIncrement(&current)-1))<param.noOfBoards) {
5818
 
 
5819
 
    int res=SolveBoard(param.bop->deals[j], param.bop->target[j],
5820
 
    param.bop->solutions[j], param.bop->mode[j], &fut[j], thid);
5821
 
    if (res==1) {
5822
 
      param.solvedp->solvedBoard[j]=fut[j];
5823
 
      param.error=0;
5824
 
    }
5825
 
    else {
5826
 
      param.error=res;
5827
 
    }
5828
 
  }
5829
 
 
5830
 
  if (SetEvent(solveAllEvents[thid])==0) {
5831
 
    int errCode=GetLastError();
5832
 
    return 0;
5833
 
  }
5834
 
 
5835
 
  return 1;
5836
 
 
5837
 
}
5838
 
 
5839
 
int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp) {
5840
 
  int k, errCode;
5841
 
  DWORD res;
5842
 
  DWORD solveAllWaitResult;
5843
 
 
5844
 
  current=0;
5845
 
 
5846
 
  threadIndex=-1;
5847
 
 
5848
 
  if (bop->noOfBoards > MAXNOOFBOARDS)
5849
 
    return -201;
5850
 
 
5851
 
  for (k=0; k<noOfCores; k++) {
5852
 
    solveAllEvents[k]=CreateEvent(NULL, FALSE, FALSE, 0);
5853
 
    if (solveAllEvents[k]==0) {
5854
 
      errCode=GetLastError();
5855
 
      return -202;
5856
 
    }
5857
 
  }
5858
 
 
5859
 
  param.bop=bop; param.solvedp=solvedp; param.noOfBoards=bop->noOfBoards;
5860
 
 
5861
 
  for (k=0; k<MAXNOOFBOARDS; k++)
5862
 
    solvedp->solvedBoard[k].cards=0;
5863
 
 
5864
 
  for (k=0; k<noOfCores; k++) {
5865
 
    res=QueueUserWorkItem(SolveChunk, NULL, WT_EXECUTELONGFUNCTION);
5866
 
    if (res!=1) {
5867
 
      errCode=GetLastError();
5868
 
      return res;
5869
 
    }
5870
 
  }
5871
 
 
5872
 
  solveAllWaitResult = WaitForMultipleObjects(noOfCores,
5873
 
          solveAllEvents, TRUE, INFINITE);
5874
 
  if (solveAllWaitResult!=WAIT_OBJECT_0) {
5875
 
    errCode=GetLastError();
5876
 
    return -203;
5877
 
  }
5878
 
 
5879
 
  for (k=0; k<noOfCores; k++) {
5880
 
    CloseHandle(solveAllEvents[k]);
5881
 
  }
5882
 
 
5883
 
  /* Calculate number of solved boards. */
5884
 
 
5885
 
  solvedp->noOfBoards=0;
5886
 
  for (k=0; k<MAXNOOFBOARDS; k++) {
5887
 
    if (solvedp->solvedBoard[k].cards!=0)
5888
 
      solvedp->noOfBoards++;
5889
 
  }
5890
 
 
5891
 
  if (param.error==0)
5892
 
    return 1;
5893
 
  else
5894
 
    return param.error;
5895
 
}
5896
 
#else
5897
 
int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp) {
5898
 
  int k, i, res, chunk, fail;
5899
 
  struct futureTricks fut[MAXNOOFBOARDS];
5900
 
 
5901
 
  chunk=4; fail=1;
5902
 
 
5903
 
  if (bop->noOfBoards > MAXNOOFBOARDS)
5904
 
    return -101;
5905
 
 
5906
 
  for (i=0; i<MAXNOOFBOARDS; i++)
5907
 
      solvedp->solvedBoard[i].cards=0;
5908
 
 
5909
 
  omp_set_num_threads(noOfCores);       /* Added after suggestion by Dirk Willecke. */
5910
 
 
5911
 
  #pragma omp parallel shared(bop, solvedp, chunk, fail) private(k)
5912
 
  {
5913
 
 
5914
 
    #pragma omp for schedule(dynamic, chunk)
5915
 
 
5916
 
    for (k=0; k<bop->noOfBoards; k++) {
5917
 
      res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k],
5918
 
        bop->mode[k], &fut[k], omp_get_thread_num());
5919
 
      if (res==1) {
5920
 
        solvedp->solvedBoard[k]=fut[k];
5921
 
      }
5922
 
      else
5923
 
        fail=res;
5924
 
    }
5925
 
  }
5926
 
 
5927
 
  if (fail!=1)
5928
 
    return fail;
5929
 
 
5930
 
  solvedp->noOfBoards=0;
5931
 
  for (i=0; i<MAXNOOFBOARDS; i++) {
5932
 
    if (solvedp->solvedBoard[i].cards!=0)
5933
 
      solvedp->noOfBoards++;
5934
 
  }
5935
 
 
5936
 
  return 1;
5937
 
}
5938
 
 
5939
 
int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp) {
5940
 
  int k, i, res, chunk, fail;
5941
 
  struct futureTricks fut[MAXNOOFBOARDS];
5942
 
 
5943
 
  chunk=1; fail=1;
5944
 
 
5945
 
  if (bop->noOfBoards > MAXNOOFBOARDS)
5946
 
    return -101;
5947
 
 
5948
 
  for (i=0; i<MAXNOOFBOARDS; i++)
5949
 
    solvedp->solvedBoard[i].cards=0;
5950
 
 
5951
 
  omp_set_num_threads(noOfCores);       /* Added after suggestion by Dirk Willecke. */
5952
 
 
5953
 
  #pragma omp parallel shared(bop, solvedp, chunk, fail) private(k)
5954
 
  {
5955
 
 
5956
 
    #pragma omp for schedule(dynamic, chunk)
5957
 
 
5958
 
    for (k=0; k<bop->noOfBoards; k++) {
5959
 
      res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k],
5960
 
        bop->mode[k], &fut[k], omp_get_thread_num());
5961
 
      if (res==1) {
5962
 
        solvedp->solvedBoard[k]=fut[k];
5963
 
      }
5964
 
      else
5965
 
        fail=res;
5966
 
    }
5967
 
  }
5968
 
 
5969
 
  if (fail!=1)
5970
 
    return fail;
5971
 
 
5972
 
  solvedp->noOfBoards=0;
5973
 
  for (i=0; i<MAXNOOFBOARDS; i++) {
5974
 
    if (solvedp->solvedBoard[i].cards!=0)
5975
 
      solvedp->noOfBoards++;
5976
 
  }
5977
 
 
5978
 
  return 1;
5979
 
}
5980
 
#endif
5981
 
 
5982
 
int STDCALL CalcDDtable(struct ddTableDeal tableDeal, struct ddTableResults * tablep) {
5983
 
 
5984
 
  int h, s, k, ind, tr, first, res;
5985
 
  struct deal dl;
5986
 
  struct boards bo;
5987
 
  struct solvedBoards solved;
5988
 
 
5989
 
  for (h=0; h<=3; h++)
5990
 
    for (s=0; s<=3; s++)
5991
 
      dl.remainCards[h][s]=tableDeal.cards[h][s];
5992
 
 
5993
 
  for (k=0; k<=2; k++) {
5994
 
    dl.currentTrickRank[k]=0;
5995
 
    dl.currentTrickSuit[k]=0;
5996
 
  }
5997
 
 
5998
 
  ind=0; bo.noOfBoards=20;
5999
 
 
6000
 
  for (tr=4; tr>=0; tr--)
6001
 
    for (first=0; first<=3; first++) {
6002
 
      dl.first=first;
6003
 
      dl.trump=tr;
6004
 
      bo.deals[ind]=dl;
6005
 
      bo.target[ind]=-1;
6006
 
      bo.solutions[ind]=1;
6007
 
      bo.mode[ind]=1;
6008
 
      ind++;
6009
 
    }
6010
 
 
6011
 
  res=SolveAllBoards4(&bo, &solved);
6012
 
  if (res==1) {
6013
 
    for (ind=0; ind<20; ind++) {
6014
 
      tablep->resTable[bo.deals[ind].trump][rho[bo.deals[ind].first]]=
6015
 
            13-solved.solvedBoard[ind].score[0];
6016
 
    }
6017
 
    return 1;
6018
 
  }
6019
 
 
6020
 
  return res;
6021
 
}
6022
 
 
6023
 
int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]) {
6024
 
  int bp=0, first, card, hand, handRelFirst, suitInHand, h, s;
6025
 
  int IsCard(char cardChar);
6026
 
 
6027
 
  for (h=0; h<=3; h++)
6028
 
    for (s=0; s<=3; s++)
6029
 
      remainCards[h][s]=0;
6030
 
 
6031
 
  while (((dealBuff[bp]!='W')&&(dealBuff[bp]!='N')&&
6032
 
        (dealBuff[bp]!='E')&&(dealBuff[bp]!='S')&&
6033
 
        (dealBuff[bp]!='w')&&(dealBuff[bp]!='n')&&
6034
 
        (dealBuff[bp]!='e')&&(dealBuff[bp]!='s'))&&(bp<3))
6035
 
    bp++;
6036
 
 
6037
 
  if (bp>=3)
6038
 
    return 0;
6039
 
 
6040
 
  if ((dealBuff[bp]=='N')||(dealBuff[bp]=='n'))
6041
 
    first=0;
6042
 
  else if ((dealBuff[bp]=='E')||(dealBuff[bp]=='e'))
6043
 
    first=1;
6044
 
  else if ((dealBuff[bp]=='S')||(dealBuff[bp]=='s'))
6045
 
    first=2;
6046
 
  else
6047
 
    first=3;
6048
 
 
6049
 
  bp++;
6050
 
  bp++;
6051
 
 
6052
 
  handRelFirst=0;  suitInHand=0;
6053
 
 
6054
 
  while ((bp<80)&&(dealBuff[bp]!='\0')) {
6055
 
    card=IsCard(dealBuff[bp]);
6056
 
    if (card) {
6057
 
      switch (first) {
6058
 
        case 0:
6059
 
          hand=handRelFirst;
6060
 
          break;
6061
 
        case 1:
6062
 
          if (handRelFirst==0)
6063
 
            hand=1;
6064
 
          else if (handRelFirst==3)
6065
 
            hand=0;
6066
 
          else
6067
 
            hand=handRelFirst+1;
6068
 
            break;
6069
 
        case 2:
6070
 
          if (handRelFirst==0)
6071
 
            hand=2;
6072
 
          else if (handRelFirst==1)
6073
 
            hand=3;
6074
 
          else
6075
 
            hand=handRelFirst-2;
6076
 
          break;
6077
 
        default:
6078
 
          if (handRelFirst==0)
6079
 
            hand=3;
6080
 
          else
6081
 
            hand=handRelFirst-1;
6082
 
      }
6083
 
 
6084
 
      remainCards[hand][suitInHand]|=(bitMapRank[card]<<2);
6085
 
 
6086
 
    }
6087
 
    else if (dealBuff[bp]=='.')
6088
 
      suitInHand++;
6089
 
    else if (dealBuff[bp]==' ') {
6090
 
      handRelFirst++;
6091
 
      suitInHand=0;
6092
 
    }
6093
 
    bp++;
6094
 
  }
6095
 
  return 1;
6096
 
}
6097
 
 
6098
 
int IsCard(char cardChar)   {
6099
 
  switch (cardChar)  {
6100
 
    case '2':
6101
 
      return 2;
6102
 
    case '3':
6103
 
      return 3;
6104
 
    case '4':
6105
 
      return 4;
6106
 
    case '5':
6107
 
      return 5;
6108
 
    case '6':
6109
 
      return 6;
6110
 
    case '7':
6111
 
      return 7;
6112
 
    case '8':
6113
 
      return 8;
6114
 
    case '9':
6115
 
      return 9;
6116
 
    case 'T':
6117
 
      return 10;
6118
 
    case 'J':
6119
 
      return 11;
6120
 
    case 'Q':
6121
 
      return 12;
6122
 
    case 'K':
6123
 
      return 13;
6124
 
    case 'A':
6125
 
      return 14;
6126
 
    case 't':
6127
 
      return 10;
6128
 
    case 'j':
6129
 
      return 11;
6130
 
    case 'q':
6131
 
      return 12;
6132
 
    case 'k':
6133
 
      return 13;
6134
 
    case 'a':
6135
 
      return 14;
6136
 
    default:
6137
 
      return 0;
6138
 
   }
6139
 
 }
6140
 
 
6141
 
#ifdef PBN 
6142
 
int STDCALL SolveBoardPBN(struct dealPBN dlpbn, int target,
6143
 
    int solutions, int mode, struct futureTricks *futp, int thrId) {
6144
 
 
6145
 
  int res, k;
6146
 
  struct deal dl;
6147
 
  int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]);
6148
 
 
6149
 
  if (ConvertFromPBN(dlpbn.remainCards, dl.remainCards)!=1)
6150
 
    return -99;
6151
 
 
6152
 
  for (k=0; k<=2; k++) {
6153
 
    dl.currentTrickRank[k]=dlpbn.currentTrickRank[k];
6154
 
    dl.currentTrickSuit[k]=dlpbn.currentTrickSuit[k];
6155
 
  }
6156
 
  dl.first=dlpbn.first;
6157
 
  dl.trump=dlpbn.trump;
6158
 
 
6159
 
  res=SolveBoard(dl, target, solutions, mode, futp, thrId);
6160
 
 
6161
 
  return res;
6162
 
}
6163
 
 
6164
 
int STDCALL CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, struct ddTableResults * tablep) {
6165
 
  struct ddTableDeal tableDeal;
6166
 
  int res;
6167
 
 
6168
 
  if (ConvertFromPBN(tableDealPBN.cards, tableDeal.cards)!=1)
6169
 
    return -99;
6170
 
 
6171
 
  res=CalcDDtable(tableDeal, tablep);
6172
 
 
6173
 
  return res;
6174
 
}
6175
 
#endif
6176
 
 
6177
 
#ifdef PBN_PLUS
6178
 
int STDCALL SolveAllBoards(struct boardsPBN *bop, struct solvedBoards *solvedp) {
6179
 
  struct boards bo;
6180
 
  int k, i, res;
6181
 
 
6182
 
  bo.noOfBoards=bop->noOfBoards;
6183
 
  for (k=0; k<bop->noOfBoards; k++) {
6184
 
    bo.mode[k]=bop->mode[k];
6185
 
    bo.solutions[k]=bop->solutions[k];
6186
 
    bo.target[k]=bop->target[k];
6187
 
    bo.deals[k].first=bop->deals[k].first;
6188
 
    bo.deals[k].trump=bop->deals[k].trump;
6189
 
    for (i=0; i<=2; i++) {
6190
 
      bo.deals[k].currentTrickSuit[i]=bop->deals[k].currentTrickSuit[i];
6191
 
      bo.deals[k].currentTrickRank[i]=bop->deals[k].currentTrickRank[i];
6192
 
    }
6193
 
    if (ConvertFromPBN(bop->deals[k].remainCards, bo.deals[k].remainCards)!=1)
6194
 
          return -99;
6195
 
  }
6196
 
 
6197
 
  res=SolveAllBoards1(&bo, solvedp);
6198
 
 
6199
 
  return res;
6200
 
}
6201
 
#endif
6202
 
 
6203
 
#ifdef PBN_PLUS
6204
 
int STDCALL CalcParPBN(struct ddTableDealPBN tableDealPBN, 
6205
 
  struct ddTableResults * tablep, int vulnerable, struct parResults *presp) {
6206
 
  int res;
6207
 
  struct ddTableDeal tableDeal;
6208
 
  int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]);
6209
 
  int STDCALL CalcPar(struct ddTableDeal tableDeal, int vulnerable, 
6210
 
    struct ddTableResults * tablep, struct parResults *presp);
6211
 
 
6212
 
  if (ConvertFromPBN(tableDealPBN.cards, tableDeal.cards)!=1)
6213
 
    return -99;
6214
 
 
6215
 
  res=CalcPar(tableDeal, vulnerable, tablep, presp);
6216
 
 
6217
 
  return res;
6218
 
}
6219
 
 
6220
 
int STDCALL CalcPar(struct ddTableDeal tableDeal, int vulnerable, 
6221
 
    struct ddTableResults * tablep, struct parResults *presp) {
6222
 
 
6223
 
  int res;
6224
 
 
6225
 
  int Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable);
6226
 
 
6227
 
  res=CalcDDtable(tableDeal, tablep);
6228
 
 
6229
 
  if (res!=1)
6230
 
    return res;
6231
 
 
6232
 
  res=Par(tablep, presp, vulnerable);
6233
 
 
6234
 
  return res;
6235
 
 
6236
 
}
6237
 
#endif
6238
 
 
6239
 
int Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable) {
6240
 
        /* vulnerable 0: None  1: Both  2: NS  3: EW */
6241
 
 
6242
 
/* The code for calculation of par score / contracts is based upon the
6243
 
   perl code written by Matthew Kidd ACBLmerge. He has kindly given me permission
6244
 
   to include a C++ adaptation in DDS. */ 
6245
 
 
6246
 
/* The Par function computes the par result and contracts. */
6247
 
 
6248
 
  
6249
 
  int denom_conv[5]={4, 0, 1, 2, 3};
6250
 
  /* Preallocate for efficiency. These hold result from last direction
6251
 
     (N-S or E-W) examined. */
6252
 
  int i, j, k, m, isvul;
6253
 
  int current_side, both_sides_once_flag, denom_max, max_lower;
6254
 
  int new_score_flag, sc1, sc2; 
6255
 
  int prev_par_denom=0, prev_par_tricks=0;
6256
 
   
6257
 
  int ut, t1, t2, tt, score, dr, ke, tu, tu_max, t3, t4, n;
6258
 
  struct par_suits_type par_suits[5];
6259
 
  char contr_sep[2]={',','\0'};
6260
 
  char temp[8], buff[4];
6261
 
 
6262
 
  int par_denom[2] = {-1, -1};   /* 0-4 = NT,S,H,D,C */
6263
 
  int par_tricks[2] = {6, 6};    /* Initial "contract" beats 0 NT */
6264
 
  int par_score[2] = {0, 0};
6265
 
  int par_sacut[2] = {0, 0};     /* Undertricks for sacrifice (0 if not sac) */
6266
 
 
6267
 
  int rawscore(int denom, int tricks, int isvul);
6268
 
  void IniSidesString(int dr, int i, int t1, int t2, char stri[]);
6269
 
  int CalcMultiContracts(int max_lower, int tricks);
6270
 
 
6271
 
  /* Find best par result for N-S (i==0) or E-W (i==1). These will
6272
 
     nearly always be the same, but when we have a "hot" situation
6273
 
     they will not be. */
6274
 
 
6275
 
  for (i=0; i<=1; i++) {
6276
 
    /* Start with the with the offensive side (current_side = 0) and alternate
6277
 
       between sides seeking the to improve the result for the current side.*/
6278
 
 
6279
 
    current_side=0;  both_sides_once_flag=0;
6280
 
    while (1) {
6281
 
 
6282
 
      /* Find best contract for current side that beats current contract.
6283
 
         Choose highest contract if results are equal. */
6284
 
 
6285
 
      k=(i+current_side) % 2;
6286
 
 
6287
 
      isvul=((vulnerable==1)||(k ? (vulnerable==3) : (vulnerable==2)));
6288
 
 
6289
 
      new_score_flag=0;
6290
 
      prev_par_denom=par_denom[i];
6291
 
      prev_par_tricks=par_tricks[i];
6292
 
 
6293
 
    /* Calculate tricks and score values and 
6294
 
       store them for each denomination in structure par_suits[5]. */
6295
 
 
6296
 
      for (j=0; j<=4; j++) {
6297
 
        t1 = k ? tablep->resTable[denom_conv[j]][1] : tablep->resTable[denom_conv[j]][0];
6298
 
        t2 = k ? tablep->resTable[denom_conv[j]][3] : tablep->resTable[denom_conv[j]][2];
6299
 
        tt = Max(t1, t2);
6300
 
        /* tt is the maximum number of tricks current side can take in 
6301
 
           denomination.*/
6302
 
        par_suits[j].suit=j;
6303
 
        par_suits[j].tricks=tt;
6304
 
        if ((tt > par_tricks[i]) || ((tt == par_tricks[i]) &&
6305
 
          (j < par_denom[i]))) 
6306
 
          par_suits[j].score=rawscore(j, tt, isvul);
6307
 
        else
6308
 
          par_suits[j].score=rawscore(-1, prev_par_tricks - tt, isvul);
6309
 
      }
6310
 
                
6311
 
       /* Sort the items in the par_suits structure with decreasing order of the 
6312
 
       values on the scores. */
6313
 
          
6314
 
      for (int s = 1; s < 5; s++) { 
6315
 
        struct par_suits_type tmp = par_suits[s]; 
6316
 
        int r = s; 
6317
 
        for (; r && tmp.score > par_suits[r - 1].score ; --r) 
6318
 
          par_suits[r] = par_suits[r - 1]; 
6319
 
        par_suits[r] = tmp; 
6320
 
      }
6321
 
          
6322
 
      /* Do the iteration as before but now in the order of the sorted denominations. */
6323
 
                
6324
 
      for (m=0; m<=4; m++) {
6325
 
        j=par_suits[m].suit;
6326
 
        tt=par_suits[m].tricks;
6327
 
 
6328
 
        if ((tt > par_tricks[i]) || ((tt == par_tricks[i]) &&
6329
 
          (j < par_denom[i]))) {
6330
 
          /* Can bid higher and make contract.*/
6331
 
          score=rawscore(j, tt, isvul);
6332
 
        }
6333
 
        else {
6334
 
          /* Bidding higher in this denomination will not beat previous denomination
6335
 
             and may be a sacrifice. */
6336
 
          ut=prev_par_tricks - tt;
6337
 
          if (j >= prev_par_denom) {
6338
 
            /* Sacrifices higher than 7N are not permitted (but long ago
6339
 
               the official rules did not prohibit bidding higher than 7N!) */
6340
 
            if (prev_par_tricks == 13)
6341
 
              continue;
6342
 
            /* It will be necessary to bid one level higher, resulting in
6343
 
               one more undertrick. */
6344
 
            ut++;
6345
 
          }
6346
 
          /* Not a sacrifice (due to par_tricks > prev_par_tricks) */
6347
 
          if (ut <= 0)
6348
 
            continue;
6349
 
          /* Compute sacrifice.*/
6350
 
          score=rawscore(-1, ut, isvul);
6351
 
        }
6352
 
        if (current_side == 1)
6353
 
          score=-score;
6354
 
 
6355
 
        if (((current_side == 0)&&(score > par_score[i])) || 
6356
 
          ((current_side == 1)&&(score < par_score[i]))) {
6357
 
          new_score_flag = 1;
6358
 
          par_score[i] = score;
6359
 
          par_denom[i] = j;             
6360
 
 
6361
 
          if (((current_side == 0)&&(score > 0)) || 
6362
 
            ((current_side == 1)&&(score < 0))) {
6363
 
            /* New par score from a making contract. 
6364
 
               Can immediately update since score at same level in higher
6365
 
               ranking suit is always >= score in lower ranking suit and 
6366
 
               better than any sacrifice. */
6367
 
            par_tricks[i] = tt;
6368
 
            par_sacut[i] = 0;
6369
 
          }
6370
 
          else {
6371
 
            par_tricks[i] = tt + ut;
6372
 
            par_sacut[i] = ut;
6373
 
          }
6374
 
        }
6375
 
      }
6376
 
 
6377
 
      if (!new_score_flag && both_sides_once_flag)
6378
 
        break; 
6379
 
      both_sides_once_flag = 1;
6380
 
      current_side = 1 - current_side;
6381
 
    }
6382
 
  }
6383
 
 
6384
 
  presp->parScore[0][0]='N';
6385
 
  presp->parScore[0][1]='S';
6386
 
  presp->parScore[0][2]=' ';
6387
 
  presp->parScore[0][3]='\0';
6388
 
  presp->parScore[1][0]='E';
6389
 
  presp->parScore[1][1]='W';
6390
 
  presp->parScore[1][2]=' ';
6391
 
  presp->parScore[1][3]='\0';
6392
 
 
6393
 
  itoa(par_score[0], temp, 10);
6394
 
  strcat(presp->parScore[0], temp);
6395
 
  itoa(par_score[1], temp, 10);
6396
 
  strcat(presp->parScore[1], temp);
6397
 
 
6398
 
  for (i=0; i<=1; i++) {
6399
 
    presp->parContractsString[0][0]='N';
6400
 
    presp->parContractsString[0][1]='S';
6401
 
    presp->parContractsString[0][2]=':';
6402
 
    presp->parContractsString[0][3]='\0';
6403
 
    presp->parContractsString[1][0]='E';
6404
 
    presp->parContractsString[1][1]='W';
6405
 
    presp->parContractsString[1][2]=':';
6406
 
    presp->parContractsString[1][3]='\0';
6407
 
  }
6408
 
 
6409
 
  if (par_score[0] == 0) {
6410
 
    /* Neither side can make anything.*/
6411
 
    return 1;
6412
 
  }
6413
 
 
6414
 
 
6415
 
  for (i=0; i<=1; i++) {
6416
 
 
6417
 
    if ( par_sacut[i] > 0 ) {
6418
 
          
6419
 
      dr = (par_score[i] > 0) ? 0 : 1;
6420
 
    
6421
 
      for (j=par_denom[i]; j<=4; j++) {
6422
 
 
6423
 
        t1 = ((dr+i) % 2 ) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1];
6424
 
        t2 = ((dr+i) % 2 ) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3];
6425
 
        tt = (t1 > t2) ? t1 : t2;
6426
 
 
6427
 
        tu_max=0;
6428
 
        for (m=4; m>=0; m--) {
6429
 
          t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1];
6430
 
          t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3];
6431
 
          tu = (t3 > t4) ? t3 : t4;
6432
 
          if (tu > tu_max) {
6433
 
            tu_max=tu;
6434
 
            denom_max=m;
6435
 
          }
6436
 
        }
6437
 
 
6438
 
 
6439
 
        if (((par_tricks[i] - par_sacut[i]) != tt)||((par_denom[i] < denom_max)&&(j > denom_max)))  
6440
 
          continue; 
6441
 
 
6442
 
        /* Continue if the par denomination is lower than the denomination of the opponent's highest 
6443
 
        trick number and the current denomination is larger than the denomination of the opponent's 
6444
 
        highest trick number. */
6445
 
 
6446
 
        IniSidesString(dr, i, t1, t2, buff);
6447
 
 
6448
 
        if (presp->parContractsString[i][3]!='\0')
6449
 
          strcat(presp->parContractsString[i], contr_sep);
6450
 
 
6451
 
        strcat(presp->parContractsString[i], buff);
6452
 
 
6453
 
        itoa(par_tricks[i]-6, temp, 10);
6454
 
        buff[0]=cardSuit[denom_conv[j]];
6455
 
        buff[1]='x';
6456
 
        buff[2]='\0';
6457
 
        strcat(temp, buff);
6458
 
        strcat(presp->parContractsString[i], temp);
6459
 
 
6460
 
        stat_contr[0]++;
6461
 
      }
6462
 
    }
6463
 
    else {
6464
 
      /* Par contract is a makeable contract.*/
6465
 
      dr = (par_score[i] < 0) ? 0 : 1;
6466
 
 
6467
 
      /* If spades or diamonds, lower major / minor may also be a par contract.*/
6468
 
      ke = (par_denom[i] == 1 || par_denom[i] == 3) ? 1 : 0;
6469
 
          
6470
 
      for (j=par_denom[i]; j<=par_denom[i]+ke; j++) {
6471
 
        t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1];
6472
 
        t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3];
6473
 
        tt = (t1 > t2) ? t1 : t2;
6474
 
 
6475
 
        if (tt < par_tricks[i]) { continue; }
6476
 
 
6477
 
        IniSidesString(dr, i, t1, t2, buff);
6478
 
 
6479
 
        tu_max=0;
6480
 
        for (m=0; m<=4; m++) {
6481
 
          t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1];
6482
 
          t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3];
6483
 
          tu = (t3 > t4) ? t3 : t4;
6484
 
          if (tu > tu_max) {
6485
 
            tu_max=tu;
6486
 
            denom_max=m;  /* Lowest denomination if several denominations have max tricks. */
6487
 
          }
6488
 
        }
6489
 
 
6490
 
        if (presp->parContractsString[i][3]!='\0')
6491
 
          strcat(presp->parContractsString[i], contr_sep);
6492
 
 
6493
 
        strcat(presp->parContractsString[i], buff);
6494
 
 
6495
 
        if (denom_max < par_denom[i]) 
6496
 
          max_lower = par_tricks[i] - tu_max - 2;
6497
 
        else
6498
 
          max_lower = par_tricks[i] - tu_max - 1;
6499
 
 
6500
 
        /* max_lower is the maximal contract lowering, otherwise opponent contract is
6501
 
        higher. It is already known that par_score is high enough to make
6502
 
        opponent sacrifices futile. 
6503
 
        To find the actual contract lowering allowed, it must be checked that the
6504
 
        lowered contract still gets the score bonus points that is present in par score.*/
6505
 
 
6506
 
        while (max_lower > 0) {
6507
 
          if (denom_max < par_denom[i]) 
6508
 
            sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max, isvul);
6509
 
          else
6510
 
            sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max + 1, isvul);
6511
 
          /* Score for undertricks needed to beat the tentative lower par contract.*/
6512
 
          sc2 = rawscore(par_denom[i], par_tricks[i] - max_lower, isvul);
6513
 
          /* Score for making the tentative lower par contract. */
6514
 
          if (sc2 < sc1)
6515
 
            break;
6516
 
          else
6517
 
            max_lower--;
6518
 
          /* Tentative lower par contract must be 1 trick higher, since the cost
6519
 
          for the sacrifice is too small. */
6520
 
        }
6521
 
 
6522
 
        switch (par_denom[i]) {
6523
 
          case 0:  k = 0; break;
6524
 
          case 1:  case 2: k = 1; break;
6525
 
          case 3:  case 4: k = 2;
6526
 
        }
6527
 
 
6528
 
        max_lower = Min(max_low[k][par_tricks[i]-6], max_lower);
6529
 
 
6530
 
        n = CalcMultiContracts(max_lower, par_tricks[i]);
6531
 
 
6532
 
        itoa(n, temp, 10);
6533
 
        buff[0]=cardSuit[denom_conv[j]];
6534
 
        buff[1]='\0';
6535
 
        strcat(temp, buff);
6536
 
        strcat(presp->parContractsString[i], temp);
6537
 
 
6538
 
        stat_contr[1]++;
6539
 
      }
6540
 
 
6541
 
 
6542
 
      /* Deal with special case of 3N/5m (+400/600) */
6543
 
      if ((par_denom[i] == 0) && (par_tricks[i] == 9)) {
6544
 
            
6545
 
        for (j=3; j<=4; j++) {
6546
 
          t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1];
6547
 
          t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3];
6548
 
          tt = (t1 > t2) ? t1 : t2;
6549
 
 
6550
 
          if (tt != 11) { continue; }
6551
 
 
6552
 
          IniSidesString(dr, i, t1, t2, buff);
6553
 
 
6554
 
          if (presp->parContractsString[i][3]!='\0')
6555
 
            strcat(presp->parContractsString[i], contr_sep);
6556
 
 
6557
 
          strcat(presp->parContractsString[i], buff);
6558
 
 
6559
 
          itoa(5, temp, 10);
6560
 
          buff[0]=cardSuit[denom_conv[j]];
6561
 
          buff[1]='\0';
6562
 
          strcat(temp, buff);
6563
 
          strcat(presp->parContractsString[i], temp);
6564
 
 
6565
 
          stat_contr[2]++;
6566
 
        }
6567
 
            
6568
 
      }
6569
 
      /* Deal with special case of 2S/2H (+110) which may have 3C and 3D
6570
 
         as additional par contract(s).*/
6571
 
      if ((par_denom[i] <=2) && (par_denom[i] != 0) && (par_tricks[i] == 8)) {
6572
 
        /* Check if 3C and 3D make.*/
6573
 
        for (j=3; j<=4; j++) {
6574
 
          t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1];
6575
 
          t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3];
6576
 
          tt = (t1 > t2) ? t1 : t2;
6577
 
 
6578
 
          if (tt != 9) { continue; }
6579
 
 
6580
 
          IniSidesString(dr, i, t1, t2, buff);
6581
 
 
6582
 
          tu_max=0;
6583
 
 
6584
 
          for (m=4; m>=0; m--) {
6585
 
            t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1];
6586
 
            t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3];
6587
 
            tu = (t3 > t4) ? t3 : t4;
6588
 
            if (tu > tu_max) {
6589
 
              tu_max=tu;
6590
 
              denom_max=m;
6591
 
            }
6592
 
          }
6593
 
 
6594
 
          if (presp->parContractsString[i][3]!='\0')
6595
 
            strcat(presp->parContractsString[i], contr_sep);
6596
 
 
6597
 
          strcat(presp->parContractsString[i], buff);
6598
 
 
6599
 
          if (denom_max < par_denom[i]) 
6600
 
            max_lower = 9 - tu_max - 2;
6601
 
          else
6602
 
            max_lower = 9 - tu_max - 1;
6603
 
 
6604
 
          /* max_lower is the maximal contract lowering, otherwise opponent contract is
6605
 
          higher. It is already known that par_score is high enough to make
6606
 
          opponent sacrifices futile. 
6607
 
          To find the actual contract lowering allowed, it must be checked that the
6608
 
          lowered contract still gets the score bonus points that is present in par score.*/
6609
 
 
6610
 
          while (max_lower > 0) {
6611
 
            if (denom_max < par_denom[i]) 
6612
 
              sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max, isvul);
6613
 
            else
6614
 
              sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max + 1, isvul);
6615
 
            /* Score for undertricks needed to beat the tentative lower par contract.*/
6616
 
            sc2 = rawscore(par_denom[i], par_tricks[i] - max_lower, isvul);
6617
 
            /* Score for making the tentative lower par contract. */
6618
 
            if (sc2 < sc1)
6619
 
              break;
6620
 
            else
6621
 
              max_lower--;
6622
 
            /* Tentative lower par contract must be 1 trick higher, since the cost
6623
 
            for the sacrifice is too small. */
6624
 
          }
6625
 
 
6626
 
          switch (par_denom[i]) {
6627
 
            case 0:  k = 0; break;
6628
 
            case 1:  case 2: k = 1; break;
6629
 
            case 3:  case 4: k = 2;
6630
 
          }
6631
 
 
6632
 
          max_lower = Min(max_low[k][3], max_lower);
6633
 
 
6634
 
          n = CalcMultiContracts(max_lower, 9);
6635
 
 
6636
 
          itoa(n, temp, 10);
6637
 
          buff[0]=cardSuit[denom_conv[j]];
6638
 
          buff[1]='\0';
6639
 
          strcat(temp, buff);
6640
 
          strcat(presp->parContractsString[i], temp);
6641
 
 
6642
 
          stat_contr[3]++;
6643
 
        }
6644
 
      }
6645
 
      /* Deal with special case 1NT (+90) which may have 2C or 2D as additonal par
6646
 
         contracts(s). */
6647
 
      if ((par_denom[i] == 0) && (par_tricks[i] == 7)) {
6648
 
        for (j=3; j<=4; j++) {
6649
 
          t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1];
6650
 
          t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3];
6651
 
          tt = (t1 > t2) ? t1 : t2;
6652
 
 
6653
 
          if (tt != 8) { continue; }
6654
 
 
6655
 
          IniSidesString(dr, i, t1, t2, buff);
6656
 
 
6657
 
          tu_max=0;
6658
 
          for (m=4; m>=0; m--) {
6659
 
            t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1];
6660
 
            t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3];
6661
 
            tu = (t3 > t4) ? t3 : t4;
6662
 
            if (tu > tu_max) {
6663
 
              tu_max=tu;
6664
 
              denom_max=m;
6665
 
            }
6666
 
          }
6667
 
 
6668
 
          if (presp->parContractsString[i][3]!='\0')
6669
 
            strcat(presp->parContractsString[i], contr_sep);
6670
 
 
6671
 
          strcat(presp->parContractsString[i], buff);
6672
 
 
6673
 
          if (denom_max < par_denom[i]) 
6674
 
            max_lower = 8 - tu_max - 2;
6675
 
          else
6676
 
            max_lower = 8 - tu_max - 1;
6677
 
 
6678
 
          /* max_lower is the maximal contract lowering, otherwise opponent contract is
6679
 
          higher. It is already known that par_score is high enough to make
6680
 
          opponent sacrifices futile. 
6681
 
          To find the actual contract lowering allowed, it must be checked that the
6682
 
          lowered contract still gets the score bonus points that is present in par score.*/
6683
 
 
6684
 
          while (max_lower > 0) {
6685
 
            if (denom_max < par_denom[i]) 
6686
 
              sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max, isvul);
6687
 
            else
6688
 
              sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max + 1, isvul);
6689
 
            /* Score for undertricks needed to beat the tentative lower par contract.*/
6690
 
            sc2 = rawscore(par_denom[i], par_tricks[i] - max_lower, isvul);
6691
 
            /* Score for making the tentative lower par contract. */
6692
 
            if (sc2 < sc1)
6693
 
              break;
6694
 
            else
6695
 
              max_lower--;
6696
 
            /* Tentative lower par contract must be 1 trick higher, since the cost
6697
 
            for the sacrifice is too small. */
6698
 
          }
6699
 
 
6700
 
          switch (par_denom[i]) {
6701
 
            case 0:  k = 0; break;
6702
 
            case 1:  case 2: k = 1; break;
6703
 
            case 3:  case 4: k = 2;
6704
 
          }
6705
 
 
6706
 
          max_lower = Min(max_low[k][3], max_lower);
6707
 
 
6708
 
          n = CalcMultiContracts(max_lower, 8);
6709
 
 
6710
 
          itoa(n, temp, 10);
6711
 
          buff[0]=cardSuit[denom_conv[j]];
6712
 
          buff[1]='\0';
6713
 
          strcat(temp, buff);
6714
 
          strcat(presp->parContractsString[i], temp);
6715
 
 
6716
 
          stat_contr[4]++;
6717
 
        }
6718
 
      }
6719
 
    }
6720
 
  }
6721
 
 
6722
 
  return 1;
6723
 
}
6724
 
 
6725
 
 
6726
 
int rawscore(int denom, int tricks, int isvul) {
6727
 
  int game_bonus, level, score;
6728
 
 
6729
 
  /* Computes score for undoubled contract or a doubled contract with
6730
 
     for a given number of undertricks. These are the only possibilities
6731
 
     for a par contract (aside from a passed out hand). 
6732
 
  
6733
 
     denom  - 0 = NT, 1 = Spades, 2 = Hearts, 3 = Diamonds, 4 = Clubs
6734
 
             (same order as results from double dummy solver); -1 undertricks
6735
 
     tricks - For making contracts (7-13); otherwise, number of undertricks.
6736
 
     isvul  - True if vulnerable */
6737
 
 
6738
 
  if (denom==-1) {
6739
 
    if (isvul)
6740
 
      return -300 * tricks + 100;
6741
 
    if (tricks<=3)
6742
 
      return -200 * tricks + 100;
6743
 
    return -300 * tricks + 400;
6744
 
  }
6745
 
  else {
6746
 
    level=tricks-6;
6747
 
    game_bonus=0;
6748
 
    if (denom==0) {
6749
 
      score=10 + 30 * level;
6750
 
      if (level>=3)
6751
 
        game_bonus=1;
6752
 
    }
6753
 
    else if ((denom==1)||(denom==2)) {
6754
 
      score=30 * level;
6755
 
      if (level>=4)
6756
 
        game_bonus=1;
6757
 
    }
6758
 
    else {
6759
 
      score=20 * level;
6760
 
      if (level>=5)
6761
 
        game_bonus=1;
6762
 
    }
6763
 
    if (game_bonus) {
6764
 
      score+= (isvul ? 500 : 300);
6765
 
    }
6766
 
    else
6767
 
      score+=50;
6768
 
 
6769
 
    if (level==6) {
6770
 
      score+= (isvul ? 750 : 500);
6771
 
    }
6772
 
    else if (level==7) {
6773
 
      score+= (isvul ? 1500 : 1000);
6774
 
    }
6775
 
  }
6776
 
 
6777
 
  return score;
6778
 
}
6779
 
 
6780
 
 
6781
 
void IniSidesString(int dr, int i, int t1, int t2, char stri[]) {
6782
 
 
6783
 
   if ((dr+i) % 2 ) {
6784
 
     if (t1==t2) {
6785
 
       stri[0]='N';
6786
 
       stri[1]='S';
6787
 
       stri[2]=' ';
6788
 
       stri[3]='\0';
6789
 
     }
6790
 
     else if (t1 > t2) {
6791
 
       stri[0]='N';
6792
 
       stri[1]=' ';
6793
 
       stri[2]='\0';
6794
 
     }
6795
 
     else {
6796
 
       stri[0]='S';
6797
 
       stri[1]=' ';
6798
 
       stri[2]='\0';
6799
 
     }
6800
 
   }
6801
 
   else {
6802
 
     if (t1==t2) {
6803
 
       stri[0]='E';
6804
 
       stri[1]='W';
6805
 
       stri[2]=' ';
6806
 
       stri[3]='\0';
6807
 
     }
6808
 
     else if (t1 > t2) {
6809
 
       stri[0]='E';
6810
 
       stri[1]=' ';
6811
 
       stri[2]='\0';
6812
 
     }
6813
 
     else {
6814
 
       stri[0]='W';
6815
 
       stri[1]=' ';
6816
 
       stri[2]='\0';
6817
 
     }
6818
 
   }
6819
 
   return;
6820
 
}
6821
 
 
6822
 
 
6823
 
int CalcMultiContracts(int max_lower, int tricks) {
6824
 
  int n;
6825
 
 
6826
 
  switch (tricks-6) {
6827
 
    case 5: if (max_lower==3) {n = 2345;}
6828
 
            else if (max_lower==2) {n = 345;}
6829
 
            else if (max_lower==1) {n = 45;}
6830
 
            else {n = 5;}
6831
 
            break;
6832
 
    case 4: if (max_lower==3) {n = 1234;}
6833
 
            else if (max_lower==2) {n = 234;}
6834
 
            else if (max_lower==1) {n = 34;}
6835
 
            else {n = 4;}
6836
 
            break;
6837
 
    case 3: if (max_lower==2) {n = 123;}
6838
 
            else if (max_lower==1) {n = 23;}
6839
 
            else {n = 3;}
6840
 
            break;
6841
 
    case 2: if (max_lower==1) {n = 12;}
6842
 
            else {n = 2;}
6843
 
            break;
6844
 
    default: n = tricks-6;
6845
 
  }
6846
 
  return n;
6847
 
}
6848
 
 
6849
 
 
6850
 
 
6851