~ubuntu-branches/ubuntu/raring/dds/raring

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Christoph Berg
  • Date: 2011-12-31 18:02:22 UTC
  • mfrom: (11.2.2 sid)
  • Revision ID: package-import@ubuntu.com-20111231180222-ftl7vynb2iftg16m
Tags: 2.1.2+ddd105-1
* New dds upstream version.
* Update watch file to mangle the ddd version to 1.0.5.
* Source format 3.0.
* Update to dh_python2, supporting multiple python versions in parallel.

Show diffs side-by-side

added added

removed removed

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