2
/* DDS 2.3.0 A bridge double dummy solver. */
3
/* Copyright (C) 2006-2012 by Bo Haglund */
4
/* Cleanups and porting to Linux and MacOSX (C) 2006 by Alex Martelli. */
5
/* The code for calculation of par score / contracts is based upon the */
6
/* perl code written by Matthew Kidd for ACBLmerge. He has kindly given me */
7
/* permission to include a C++ adaptation in DDS. */
9
/* Licensed under the Apache License, Version 2.0 (the "License"); */
10
/* you may not use this file except in compliance with the License. */
11
/* You may obtain a copy of the License at */
12
/* http://www.apache.org/licenses/LICENSE-2.0 */
13
/* Unless required by applicable law or agreed to in writing, software */
14
/* distributed under the License is distributed on an "AS IS" BASIS, */
15
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
16
/* See the License for the specific language governing permissions and */
17
/* limitations under the License. */
20
/*#include "stdafx.h"*/ /* Needed by Visual C++ */
24
struct localVarType localVar[MAXNOOFTHREADS];
31
unsigned short int bitMapRank[16];
32
unsigned char cardRank[15];
33
unsigned char cardSuit[5];
34
unsigned char cardHand[4];
35
int stat_contr[5]={0,0,0,0,0};
36
int max_low[3][8]; /* index 1: 0=NT, 1=Major, 2=Minor index 2: contract level 1-7 */
38
struct ttStoreType * ttStore;
43
int noOfThreads=MAXNOOFTHREADS; /* The number of entries to the transposition tables. There is
44
one entry per thread. */
45
int noOfCores; /* The number of processor cores, however cannot be higher than noOfThreads. */
48
#pragma managed(push, off)
53
extern "C" BOOL APIENTRY DllMain(HMODULE hModule,
54
DWORD ul_reason_for_call,
58
if (ul_reason_for_call==DLL_PROCESS_ATTACH) {
61
else if (ul_reason_for_call==DLL_PROCESS_DETACH) {
62
for (k=0; k<noOfThreads; k++) {
64
if (localVar[k].pw[0])
65
free(localVar[k].pw[0]);
66
localVar[k].pw[0]=NULL;
67
if (localVar[k].pn[0])
68
free(localVar[k].pn[0]);
69
localVar[k].pn[0]=NULL;
70
if (localVar[k].pl[0])
71
free(localVar[k].pl[0]);
72
localVar[k].pl[0]=NULL;
83
free(localVar[k].rel);
85
if (localVar[k].adaptWins)
86
free(localVar[k].adaptWins);
87
localVar[k].adaptWins=NULL;
98
/*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */
108
int STDCALL SolveBoard(struct deal dl, int target,
109
int solutions, int mode, struct futureTricks *futp, int thrId) {
111
int k, n, cardCount, found, totalTricks, tricks, last, checkRes;
112
int g, upperbound, lowerbound, first, i, j, h, forb, ind, flag, noMoves;
116
int noOfCardsPerHand[4];
117
int latestTrickSuit[4];
118
int latestTrickRank[4];
119
int maxHand=0, maxSuit=0, maxRank;
120
unsigned short int aggrRemain;
121
struct movePlyType temp;
123
int hiwinSetSize=0, hinodeSetSize=0;
125
int MaxnodeSetSize=0;
130
/*InitStart(0,0);*/ /* Include InitStart() if inside SolveBoard,
131
but preferable InitStart should be called outside
132
SolveBoard like in DllMain for Windows. */
134
if ((thrId<0)||(thrId>=noOfThreads)) { /* Fault corrected after suggestion by Dirk Willecke. */
135
DumpInput(-15, dl, target, solutions, mode);
139
for (k=0; k<=13; k++) {
140
localVar[thrId].forbiddenMoves[k].rank=0;
141
localVar[thrId].forbiddenMoves[k].suit=0;
145
DumpInput(-5, dl, target, solutions, mode);
149
DumpInput(-7, dl, target, solutions, mode);
153
DumpInput(-8, dl, target, solutions, mode);
157
DumpInput(-9, dl, target, solutions, mode);
162
noOfCardsPerHand[handId(dl.first, k)]=0;
165
for (k=0; k<=2; k++) {
166
if (dl.currentTrickRank[k]!=0) {
167
noOfCardsPerHand[handId(dl.first, k)]=1;
170
aggrRemain|=(dl.remainCards[h][dl.currentTrickSuit[k]]>>2);
171
if ((aggrRemain & bitMapRank[dl.currentTrickRank[k]])!=0) {
172
DumpInput(-13, dl, target, solutions, mode);
179
localVar[thrId].tricksTarget=99;
181
localVar[thrId].tricksTarget=target;
183
localVar[thrId].newDeal=FALSE; localVar[thrId].newTrump=FALSE;
184
localVar[thrId].diffDeal=0; localVar[thrId].aggDeal=0;
186
for (i=0; i<=3; i++) {
187
for (j=0; j<=3; j++) {
188
cardCount+=counttable[dl.remainCards[i][j]>>2];
189
localVar[thrId].diffDeal+=((dl.remainCards[i][j]>>2)^
190
(localVar[thrId].game.suit[i][j]));
191
localVar[thrId].aggDeal+=(dl.remainCards[i][j]>>2);
192
if (localVar[thrId].game.suit[i][j]!=dl.remainCards[i][j]>>2) {
193
localVar[thrId].game.suit[i][j]=dl.remainCards[i][j]>>2;
194
localVar[thrId].newDeal=TRUE;
199
if (localVar[thrId].newDeal) {
200
if (localVar[thrId].diffDeal==0)
201
localVar[thrId].similarDeal=TRUE;
202
else if ((localVar[thrId].aggDeal/localVar[thrId].diffDeal)
204
localVar[thrId].similarDeal=TRUE;
206
localVar[thrId].similarDeal=FALSE;
209
localVar[thrId].similarDeal=FALSE;
211
if (dl.trump!=localVar[thrId].trump)
212
localVar[thrId].newTrump=TRUE;
216
noOfCardsPerHand[i]+=counttable[localVar[thrId].game.suit[i][j]];
218
for (i=1; i<=3; i++) {
219
if (noOfCardsPerHand[i]!=noOfCardsPerHand[0]) {
220
DumpInput(-14, dl, target, solutions, mode);
225
if (dl.currentTrickRank[2]) {
226
if ((dl.currentTrickRank[2]<2)||(dl.currentTrickRank[2]>14)
227
||(dl.currentTrickSuit[2]<0)||(dl.currentTrickSuit[2]>3)) {
228
DumpInput(-12, dl, target, solutions, mode);
231
localVar[thrId].handToPlay=handId(dl.first, 3);
235
for (k=0; k<=3; k++) {
236
if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) {
237
latestTrickSuit[localVar[thrId].handToPlay]=k;
238
latestTrickRank[localVar[thrId].handToPlay]=
239
InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]);
243
latestTrickSuit[handId(dl.first, 2)]=dl.currentTrickSuit[2];
244
latestTrickRank[handId(dl.first, 2)]=dl.currentTrickRank[2];
245
latestTrickSuit[handId(dl.first, 1)]=dl.currentTrickSuit[1];
246
latestTrickRank[handId(dl.first, 1)]=dl.currentTrickRank[1];
247
latestTrickSuit[dl.first]=dl.currentTrickSuit[0];
248
latestTrickRank[dl.first]=dl.currentTrickRank[0];
251
else if (dl.currentTrickRank[1]) {
252
if ((dl.currentTrickRank[1]<2)||(dl.currentTrickRank[1]>14)
253
||(dl.currentTrickSuit[1]<0)||(dl.currentTrickSuit[1]>3)) {
254
DumpInput(-12, dl, target, solutions, mode);
257
localVar[thrId].handToPlay=handId(dl.first, 2);
261
for (k=0; k<=3; k++) {
262
if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) {
263
latestTrickSuit[localVar[thrId].handToPlay]=k;
264
latestTrickRank[localVar[thrId].handToPlay]=
265
InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]);
269
for (k=0; k<=3; k++) {
270
if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) {
271
latestTrickSuit[handId(dl.first, 3)]=k;
272
latestTrickRank[handId(dl.first, 3)]=
273
InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]);
277
latestTrickSuit[handId(dl.first, 1)]=dl.currentTrickSuit[1];
278
latestTrickRank[handId(dl.first, 1)]=dl.currentTrickRank[1];
279
latestTrickSuit[dl.first]=dl.currentTrickSuit[0];
280
latestTrickRank[dl.first]=dl.currentTrickRank[0];
283
else if (dl.currentTrickRank[0]) {
284
if ((dl.currentTrickRank[0]<2)||(dl.currentTrickRank[0]>14)
285
||(dl.currentTrickSuit[0]<0)||(dl.currentTrickSuit[0]>3)) {
286
DumpInput(-12, dl, target, solutions, mode);
289
localVar[thrId].handToPlay=handId(dl.first,1);
293
for (k=0; k<=3; k++) {
294
if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) {
295
latestTrickSuit[localVar[thrId].handToPlay]=k;
296
latestTrickRank[localVar[thrId].handToPlay]=
297
InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]);
301
for (k=0; k<=3; k++) {
302
if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) {
303
latestTrickSuit[handId(dl.first, 3)]=k;
304
latestTrickRank[handId(dl.first, 3)]=
305
InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]);
309
for (k=0; k<=3; k++) {
310
if (localVar[thrId].game.suit[handId(dl.first, 2)][k]!=0) {
311
latestTrickSuit[handId(dl.first, 2)]=k;
312
latestTrickRank[handId(dl.first, 2)]=
313
InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 2)][k]);
317
latestTrickSuit[dl.first]=dl.currentTrickSuit[0];
318
latestTrickRank[dl.first]=dl.currentTrickRank[0];
322
localVar[thrId].handToPlay=dl.first;
326
for (k=0; k<=3; k++) {
327
if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) {
328
latestTrickSuit[localVar[thrId].handToPlay]=k;
329
latestTrickRank[localVar[thrId].handToPlay]=
330
InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]);
334
for (k=0; k<=3; k++) {
335
if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) {
336
latestTrickSuit[handId(dl.first, 3)]=k;
337
latestTrickRank[handId(dl.first, 3)]=
338
InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]);
342
for (k=0; k<=3; k++) {
343
if (localVar[thrId].game.suit[handId(dl.first, 2)][k]!=0) {
344
latestTrickSuit[handId(dl.first, 2)]=k;
345
latestTrickRank[handId(dl.first, 2)]=
346
InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 2)][k]);
350
for (k=0; k<=3; k++) {
351
if (localVar[thrId].game.suit[handId(dl.first, 1)][k]!=0) {
352
latestTrickSuit[handId(dl.first, 1)]=k;
353
latestTrickRank[handId(dl.first, 1)]=
354
InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 1)][k]);
361
localVar[thrId].trump=dl.trump;
362
localVar[thrId].game.first=dl.first;
364
localVar[thrId].game.noOfCards=cardCount;
365
if (dl.currentTrickRank[0]!=0) {
366
localVar[thrId].game.leadHand=dl.first;
367
localVar[thrId].game.leadSuit=dl.currentTrickSuit[0];
368
localVar[thrId].game.leadRank=dl.currentTrickRank[0];
371
localVar[thrId].game.leadHand=0;
372
localVar[thrId].game.leadSuit=0;
373
localVar[thrId].game.leadRank=0;
376
for (k=0; k<=2; k++) {
377
localVar[thrId].initialMoves[k].suit=255;
378
localVar[thrId].initialMoves[k].rank=255;
381
for (k=0; k<noStartMoves; k++) {
382
localVar[thrId].initialMoves[noStartMoves-1-k].suit=dl.currentTrickSuit[k];
383
localVar[thrId].initialMoves[noStartMoves-1-k].rank=dl.currentTrickRank[k];
387
totalTricks=((cardCount-4)>>2)+2;
389
totalTricks=((cardCount-4)>>2)+1;
390
checkRes=CheckDeal(&localVar[thrId].cd, thrId);
391
if (localVar[thrId].game.noOfCards<=0) {
392
DumpInput(-2, dl, target, solutions, mode);
395
if (localVar[thrId].game.noOfCards>52) {
396
DumpInput(-10, dl, target, solutions, mode);
399
if (totalTricks<target) {
400
DumpInput(-3, dl, target, solutions, mode);
404
DumpInput(-4, dl, target, solutions, mode);
412
for (k=0; k<=3; k++) {
413
if ((latestTrickSuit[k]==dl.trump)&&
414
(latestTrickRank[k]>maxRank)) {
415
maxRank=latestTrickRank[k];
421
/* Highest card in leading suit */
423
for (k=0; k<=3; k++) {
425
maxSuit=latestTrickSuit[dl.first];
427
maxRank=latestTrickRank[dl.first];
431
for (k=0; k<=3; k++) {
432
if ((k!=dl.first)&&(latestTrickSuit[k]==maxSuit)&&
433
(latestTrickRank[k]>maxRank)) {
435
maxRank=latestTrickRank[k];
444
futp->suit[0]=latestTrickSuit[localVar[thrId].handToPlay];
445
futp->rank[0]=latestTrickRank[localVar[thrId].handToPlay];
447
if ((target==0)&&(solutions<3))
449
else if ((localVar[thrId].handToPlay==maxHand)||
450
(partner[localVar[thrId].handToPlay]==maxHand))
455
/*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */
460
(((localVar[thrId].newDeal)&&(!localVar[thrId].similarDeal))
461
|| localVar[thrId].newTrump ||
462
(localVar[thrId].winSetSize > SIMILARMAXWINNODES))) {
465
localVar[thrId].winSetSizeLimit=WINIT;
466
localVar[thrId].nodeSetSizeLimit=NINIT;
467
localVar[thrId].lenSetSizeLimit=LINIT;
468
localVar[thrId].allocmem=(WINIT+1)*sizeof(struct winCardType);
469
localVar[thrId].allocmem+=(NINIT+1)*sizeof(struct nodeCardsType);
470
localVar[thrId].allocmem+=(LINIT+1)*sizeof(struct posSearchType);
471
localVar[thrId].winCards=localVar[thrId].pw[0];
472
localVar[thrId].nodeCards=localVar[thrId].pn[0];
473
localVar[thrId].posSearch=localVar[thrId].pl[0];
474
localVar[thrId].wcount=0; localVar[thrId].ncount=0; localVar[thrId].lcount=0;
475
InitGame(0, FALSE, first, handRelFirst, thrId);
478
InitGame(0, TRUE, first, handRelFirst, thrId);
479
/*localVar[thrId].fp2=fopen("dyn.txt", "a");
480
fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n",
481
wcount, ncount, lcount);
482
fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n",
483
winSetSize, nodeSetSize, lenSetSize);
484
fclose(localVar[thrId].fp2);*/
487
localVar[thrId].nodes=0; localVar[thrId].trickNodes=0;
488
localVar[thrId].iniDepth=cardCount-4;
493
MoveGen(&localVar[thrId].lookAheadPos, localVar[thrId].iniDepth, localVar[thrId].trump,
494
&localVar[thrId].movePly[localVar[thrId].iniDepth], thrId);
495
if (localVar[thrId].movePly[localVar[thrId].iniDepth].last==0) {
501
futp->suit[0]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].suit;
502
futp->rank[0]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].rank;
504
localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].sequence<<2;
507
/*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */
511
if ((target==0)&&(solutions<3)) {
512
MoveGen(&localVar[thrId].lookAheadPos, localVar[thrId].iniDepth, localVar[thrId].trump,
513
&localVar[thrId].movePly[localVar[thrId].iniDepth], thrId);
518
for (k=0; k<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; k++) {
519
futp->suit[k]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].suit;
520
futp->rank[k]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].rank;
522
localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].sequence<<2;
528
futp->cards=localVar[thrId].movePly[localVar[thrId].iniDepth].last+1;
530
/*_CrtDumpMemoryLeaks(); */ /* MEMORY LEAK? */
534
if ((target!=-1)&&(solutions!=3)) {
535
localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos,
536
localVar[thrId].tricksTarget, localVar[thrId].iniDepth, thrId);
538
temp=localVar[thrId].movePly[localVar[thrId].iniDepth];
539
last=localVar[thrId].movePly[localVar[thrId].iniDepth].last;
541
hiwinSetSize=localVar[thrId].winSetSize;
542
hinodeSetSize=localVar[thrId].nodeSetSize;
543
hilenSetSize=localVar[thrId].lenSetSize;
544
if (localVar[thrId].nodeSetSize>MaxnodeSetSize)
545
MaxnodeSetSize=localVar[thrId].nodeSetSize;
546
if (localVar[thrId].winSetSize>MaxwinSetSize)
547
MaxwinSetSize=localVar[thrId].winSetSize;
548
if (localVar[thrId].lenSetSize>MaxlenSetSize)
549
MaxlenSetSize=localVar[thrId].lenSetSize;
550
if (localVar[thrId].val==1)
551
localVar[thrId].payOff=localVar[thrId].tricksTarget;
553
localVar[thrId].payOff=0;
557
if (localVar[thrId].payOff<=0) {
558
futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit;
559
futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank;
560
futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2;
561
if (localVar[thrId].tricksTarget>1)
567
futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
568
futp->rank[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
569
futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2;
570
futp->score[0]=localVar[thrId].payOff;
574
g=localVar[thrId].estTricks[localVar[thrId].handToPlay];
582
assert((localVar[thrId].lookAheadPos.handRelFirst>=0)&&
583
(localVar[thrId].lookAheadPos.handRelFirst<=3));
584
localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, tricks,
585
localVar[thrId].iniDepth, thrId);
587
if (localVar[thrId].val==TRUE)
588
mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4];
589
hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize);
590
hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize);
591
hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize);
592
if (localVar[thrId].nodeSetSize>MaxnodeSetSize)
593
MaxnodeSetSize=localVar[thrId].nodeSetSize;
594
if (localVar[thrId].winSetSize>MaxwinSetSize)
595
MaxwinSetSize=localVar[thrId].winSetSize;
596
if (localVar[thrId].lenSetSize>MaxlenSetSize)
597
MaxlenSetSize=localVar[thrId].lenSetSize;
598
if (localVar[thrId].val==FALSE) {
606
InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4,
607
localVar[thrId].initialMoves, first, TRUE, thrId);
609
while (lowerbound<upperbound);
610
localVar[thrId].payOff=g;
611
temp=localVar[thrId].movePly[localVar[thrId].iniDepth];
612
last=localVar[thrId].movePly[localVar[thrId].iniDepth].last;
615
localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]=mv;
617
if (localVar[thrId].payOff<=0) {
619
futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit;
620
futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank;
621
futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2;
624
futp->score[0]=localVar[thrId].payOff;
625
futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
626
futp->rank[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
627
futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2;
629
localVar[thrId].tricksTarget=localVar[thrId].payOff;
632
if ((solutions==2)&&(localVar[thrId].payOff>0)) {
635
while ((localVar[thrId].payOff==localVar[thrId].tricksTarget)&&(ind<(temp.last+1))) {
636
localVar[thrId].forbiddenMoves[forb].suit=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
637
localVar[thrId].forbiddenMoves[forb].rank=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
639
/* All moves before bestMove in the move list shall be
640
moved to the forbidden moves list, since none of them reached
642
mcurr=localVar[thrId].movePly[localVar[thrId].iniDepth].current;
643
for (k=0; k<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; k++)
644
if ((localVar[thrId].bestMove[localVar[thrId].iniDepth].suit==
645
localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].suit)
646
&&(localVar[thrId].bestMove[localVar[thrId].iniDepth].rank==
647
localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].rank))
649
for (i=0; i<k; i++) { /* All moves until best move */
651
for (j=0; j<forb; j++) {
652
if ((localVar[thrId].movePly[localVar[thrId].iniDepth].move[i].suit==localVar[thrId].forbiddenMoves[j].suit)
653
&&(localVar[thrId].movePly[localVar[thrId].iniDepth].move[i].rank==localVar[thrId].forbiddenMoves[j].rank)) {
654
/* If the move is already in the forbidden list */
660
localVar[thrId].forbiddenMoves[forb]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[i];
664
InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4,
665
localVar[thrId].initialMoves, first, TRUE, thrId);
666
localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, localVar[thrId].tricksTarget,
667
localVar[thrId].iniDepth, thrId);
669
hiwinSetSize=localVar[thrId].winSetSize;
670
hinodeSetSize=localVar[thrId].nodeSetSize;
671
hilenSetSize=localVar[thrId].lenSetSize;
672
if (localVar[thrId].nodeSetSize>MaxnodeSetSize)
673
MaxnodeSetSize=localVar[thrId].nodeSetSize;
674
if (localVar[thrId].winSetSize>MaxwinSetSize)
675
MaxwinSetSize=localVar[thrId].winSetSize;
676
if (localVar[thrId].lenSetSize>MaxlenSetSize)
677
MaxlenSetSize=localVar[thrId].lenSetSize;
678
if (localVar[thrId].val==TRUE) {
679
localVar[thrId].payOff=localVar[thrId].tricksTarget;
681
futp->suit[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
682
futp->rank[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
683
futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2;
684
futp->score[ind-1]=localVar[thrId].payOff;
687
localVar[thrId].payOff=0;
690
else if ((solutions==2)&&(localVar[thrId].payOff==0)&&
691
((target==-1)||(localVar[thrId].tricksTarget==1))) {
693
/* Find the cards that were in the initial move list
694
but have not been listed in the current result */
696
for (i=0; i<noMoves; i++) {
698
if ((temp.move[i].suit==futp->suit[0])&&
699
(temp.move[i].rank==futp->rank[0])) {
703
futp->suit[1+n]=temp.move[i].suit;
704
futp->rank[1+n]=temp.move[i].rank;
705
futp->equals[1+n]=(temp.move[i].sequence)<<2;
712
if ((solutions==3)&&(localVar[thrId].payOff>0)) {
715
for (i=0; i<last; i++) {
716
localVar[thrId].forbiddenMoves[forb].suit=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
717
localVar[thrId].forbiddenMoves[forb].rank=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
720
g=localVar[thrId].payOff;
721
upperbound=localVar[thrId].payOff;
724
InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4,
725
localVar[thrId].initialMoves, first, TRUE, thrId);
731
assert((localVar[thrId].lookAheadPos.handRelFirst>=0)&&
732
(localVar[thrId].lookAheadPos.handRelFirst<=3));
733
localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, tricks,
734
localVar[thrId].iniDepth, thrId);
736
if (localVar[thrId].val==TRUE)
737
mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4];
738
hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize);
739
hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize);
740
hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize);
741
if (localVar[thrId].nodeSetSize>MaxnodeSetSize)
742
MaxnodeSetSize=localVar[thrId].nodeSetSize;
743
if (localVar[thrId].winSetSize>MaxwinSetSize)
744
MaxwinSetSize=localVar[thrId].winSetSize;
745
if (localVar[thrId].lenSetSize>MaxlenSetSize)
746
MaxlenSetSize=localVar[thrId].lenSetSize;
747
if (localVar[thrId].val==FALSE) {
756
InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4,
757
localVar[thrId].initialMoves, first, TRUE, thrId);
759
while (lowerbound<upperbound);
760
localVar[thrId].payOff=g;
761
if (localVar[thrId].payOff==0) {
762
last=localVar[thrId].movePly[localVar[thrId].iniDepth].last;
763
futp->cards=temp.last+1;
764
for (j=0; j<=last; j++) {
765
futp->suit[ind-1+j]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].suit;
766
futp->rank[ind-1+j]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].rank;
767
futp->equals[ind-1+j]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].sequence)<<2;
768
futp->score[ind-1+j]=localVar[thrId].payOff;
773
localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]=mv;
776
futp->suit[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit;
777
futp->rank[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank;
778
futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2;
779
futp->score[ind-1]=localVar[thrId].payOff;
783
else if ((solutions==3)&&(localVar[thrId].payOff==0)) {
785
/* Find the cards that were in the initial move list
786
but have not been listed in the current result */
788
for (i=0; i<noMoves; i++) {
790
if ((temp.move[i].suit==futp->suit[0])&&
791
(temp.move[i].rank==futp->rank[0])) {
795
futp->suit[1+n]=temp.move[i].suit;
796
futp->rank[1+n]=temp.move[i].rank;
797
futp->equals[1+n]=(temp.move[i].sequence)<<2;
804
for (k=0; k<=13; k++) {
805
localVar[thrId].forbiddenMoves[k].suit=0;
806
localVar[thrId].forbiddenMoves[k].rank=0;
809
futp->nodes=localVar[thrId].trickNodes;
811
futp->totalNodes=localVar[thrId].nodes;
813
/*if ((wcount>0)||(ncount>0)||(lcount>0)) {
814
localVar[thrId].fp2=fopen("dyn.txt", "a");
815
fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n",
816
wcount, ncount, lcount);
817
fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n",
818
winSetSize, nodeSetSize, lenSetSize);
819
fprintf(localVar[thrId].fp2, "\n");
820
fclose(localVar[thrId].fp2);
823
/*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */
830
void InitStart(int gb_ram, int ncores) {
832
unsigned short int res;
833
unsigned long long pcmem; /* kbytes */
842
ttStore = (struct ttStoreType *)calloc(SEARCHSIZE, sizeof(struct ttStoreType));
846
if (gb_ram==0) { /* Autoconfig */
852
MEMORYSTATUSEX statex;
853
statex.dwLength = sizeof (statex);
855
GlobalMemoryStatusEx (&statex); /* Using GlobalMemoryStatusEx instead of GlobalMemoryStatus
856
was suggested by Lorne Anderson. */
858
pcmem=(unsigned long long)statex.ullTotalPhys/1024;
861
noOfThreads=Min(MAXNOOFTHREADS, 2);
862
else if (pcmem < 2500000)
863
noOfThreads=Min(MAXNOOFTHREADS, 4);
865
noOfThreads=MAXNOOFTHREADS;
867
GetSystemInfo(&temp);
868
noOfCores=Min(noOfThreads, (int)temp.dwNumberOfProcessors);
871
#ifdef __linux__ /* The code for linux was suggested by Antony Lee. */
872
FILE* fifo = popen("free -k | tail -n+3 | head -n1 | awk '{print $NF}'", "r");
873
fscanf(fifo, "%ld", &pcmem);
880
noOfThreads=Min(MAXNOOFTHREADS, 2);
882
noOfThreads=Min(MAXNOOFTHREADS, 4);
884
noOfThreads=Min(MAXNOOFTHREADS, 8);
886
noOfCores=Min(noOfThreads, ncores);
888
pcmem=(unsigned long long)(1000000 * gb_ram);
891
/*printf("noOfThreads: %d noOfCores: %d\n", noOfThreads, noOfCores);*/
893
for (k=0; k<noOfThreads; k++) {
894
localVar[k].trump=-1;
895
localVar[k].nodeSetSizeLimit=0;
896
localVar[k].winSetSizeLimit=0;
897
localVar[k].lenSetSizeLimit=0;
898
localVar[k].clearTTflag=FALSE;
899
localVar[k].windex=-1;
901
localVar[k].nodeSetSize=0; /* Index with range 0 to nodeSetSizeLimit */
902
localVar[k].winSetSize=0; /* Index with range 0 to winSetSizeLimit */
903
localVar[k].lenSetSize=0; /* Index with range 0 to lenSetSizeLimit */
905
localVar[k].nodeSetSizeLimit=NINIT;
906
localVar[k].winSetSizeLimit=WINIT;
907
localVar[k].lenSetSizeLimit=LINIT;
909
if ((gb_ram!=0)&&(ncores!=0))
910
localVar[k].maxmem=gb_ram * ((8000001*sizeof(struct nodeCardsType)+
911
25000001*sizeof(struct winCardType)+
912
400001*sizeof(struct posSearchType))/noOfThreads);
914
localVar[k].maxmem = (unsigned long long)(pcmem-32768) * (700/noOfThreads);
915
/* Linear calculation of maximum memory, formula by Michiel de Bondt */
917
if (localVar[k].maxmem < 10485760) exit (1);
920
/*printf("thread no: %d maxmem: %ld\n", k, localVar[k].maxmem);*/
923
bitMapRank[15]=0x2000;
924
bitMapRank[14]=0x1000;
925
bitMapRank[13]=0x0800;
926
bitMapRank[12]=0x0400;
927
bitMapRank[11]=0x0200;
928
bitMapRank[10]=0x0100;
929
bitMapRank[9]=0x0080;
930
bitMapRank[8]=0x0040;
931
bitMapRank[7]=0x0020;
932
bitMapRank[6]=0x0010;
933
bitMapRank[5]=0x0008;
934
bitMapRank[4]=0x0004;
935
bitMapRank[3]=0x0002;
936
bitMapRank[2]=0x0001;
940
lho[0]=1; lho[1]=2; lho[2]=3; lho[3]=0;
941
rho[0]=3; rho[1]=0; rho[2]=1; rho[3]=2;
942
partner[0]=2; partner[1]=3; partner[2]=0; partner[3]=1;
944
cardRank[2]='2'; cardRank[3]='3'; cardRank[4]='4'; cardRank[5]='5';
945
cardRank[6]='6'; cardRank[7]='7'; cardRank[8]='8'; cardRank[9]='9';
946
cardRank[10]='T'; cardRank[11]='J'; cardRank[12]='Q'; cardRank[13]='K';
949
cardSuit[0]='S'; cardSuit[1]='H'; cardSuit[2]='D'; cardSuit[3]='C';
952
cardHand[0]='N'; cardHand[1]='E'; cardHand[2]='S'; cardHand[3]='W';
954
max_low[0][0]=0; max_low[1][0]=0; max_low[2][0]=0;
955
max_low[0][1]=0; max_low[1][1]=0; max_low[2][1]=0;
956
max_low[0][2]=1; max_low[1][2]=1; max_low[2][2]=1;
957
max_low[0][3]=0; max_low[1][3]=2; max_low[2][3]=2;
958
max_low[0][4]=1; max_low[1][4]=0; max_low[2][4]=3;
959
max_low[0][5]=2; max_low[1][5]=1; max_low[2][5]=0;
960
max_low[0][6]=0; max_low[1][6]=0; max_low[2][6]=0;
961
max_low[0][7]=0; max_low[1][7]=0; max_low[2][7]=0;
963
for (k=0; k<noOfThreads; k++) {
964
localVar[k].summem=(WINIT+1)*sizeof(struct winCardType)+
965
(NINIT+1)*sizeof(struct nodeCardsType)+
966
(LINIT+1)*sizeof(struct posSearchType);
967
localVar[k].wmem=(WSIZE+1)*sizeof(struct winCardType);
968
localVar[k].nmem=(NSIZE+1)*sizeof(struct nodeCardsType);
969
localVar[k].lmem=(LSIZE+1)*sizeof(struct posSearchType);
970
localVar[k].maxIndex=(int)(
971
(localVar[k].maxmem-localVar[k].summem)/((WSIZE+1) * sizeof(struct winCardType)));
973
localVar[k].pw = (struct winCardType **)calloc(localVar[k].maxIndex+1, sizeof(struct winCardType *));
974
if (localVar[k].pw==NULL)
976
localVar[k].pn = (struct nodeCardsType **)calloc(localVar[k].maxIndex+1, sizeof(struct nodeCardsType *));
977
if (localVar[k].pn==NULL)
979
localVar[k].pl = (struct posSearchType **)calloc(localVar[k].maxIndex+1, sizeof(struct posSearchType *));
980
if (localVar[k].pl==NULL)
982
for (i=0; i<=localVar[k].maxIndex; i++) {
983
if (localVar[k].pw[i])
984
free(localVar[k].pw[i]);
985
localVar[k].pw[i]=NULL;
987
for (i=0; i<=localVar[k].maxIndex; i++) {
988
if (localVar[k].pn[i])
989
free(localVar[k].pn[i]);
990
localVar[k].pn[i]=NULL;
992
for (i=0; i<=localVar[k].maxIndex; i++) {
993
if (localVar[k].pl[i])
994
free(localVar[k].pl[i]);
995
localVar[k].pl[i]=NULL;
998
localVar[k].pw[0] = (struct winCardType *)calloc(localVar[k].winSetSizeLimit+1, sizeof(struct winCardType));
999
if (localVar[k].pw[0]==NULL)
1001
localVar[k].allocmem=(localVar[k].winSetSizeLimit+1)*sizeof(struct winCardType);
1002
localVar[k].winCards=localVar[k].pw[0];
1003
localVar[k].pn[0] = (struct nodeCardsType *)calloc(localVar[k].nodeSetSizeLimit+1, sizeof(struct nodeCardsType));
1004
if (localVar[k].pn[0]==NULL)
1006
localVar[k].allocmem+=(localVar[k].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType);
1007
localVar[k].nodeCards=localVar[k].pn[0];
1009
(struct posSearchType *)calloc(localVar[k].lenSetSizeLimit+1, sizeof(struct posSearchType));
1010
if (localVar[k].pl[0]==NULL)
1012
localVar[k].allocmem+=(localVar[k].lenSetSizeLimit+1)*sizeof(struct posSearchType);
1013
localVar[k].posSearch=localVar[k].pl[0];
1014
localVar[k].wcount=0; localVar[k].ncount=0; localVar[k].lcount=0;
1016
localVar[k].rel = (struct relRanksType *)calloc(8192, sizeof(struct relRanksType));
1017
if (localVar[k].rel==NULL)
1020
localVar[k].adaptWins = (struct adaptWinRanksType *)calloc(8192,
1021
sizeof(struct adaptWinRanksType));
1022
if (localVar[k].adaptWins==NULL)
1026
highestRank = (int *)calloc(8192, sizeof(int));
1027
if (highestRank==NULL)
1031
for (k=1; k<8192; k++) {
1032
for (r=14; r>=2; r--) {
1033
if ((k & bitMapRank[r])!=0) {
1040
/* The use of the counttable to give the number of bits set to
1041
one in an integer follows an implementation by Thomas Andrews. */
1043
counttable = (int *)calloc(8192, sizeof(int));
1044
if (counttable==NULL)
1047
for (i=0; i<8192; i++) {
1049
for (j=0; j<13; j++) {
1050
if (i & (1<<j)) {counttable[i]++;}
1055
for (i=0; i<8192; i++)
1056
for (j=0; j<14; j++) {
1059
for (m=0; m<noOfThreads; m++)
1060
localVar[m].adaptWins[i].winRanks[j]=0;
1064
for (r=14; r>=2; r--) {
1065
if ((i & bitMapRank[r])!=0) {
1074
for (m=0; m<noOfThreads; m++)
1075
localVar[m].adaptWins[i].winRanks[j]=res;
1079
/*localVar[thrId].fp2=fopen("dyn.txt", "w");
1080
fclose(localVar[thrId].fp2);*/
1081
/*localVar[thrId].fp2=fopen("dyn.txt", "a");
1082
fprintf(localVar[thrId].fp2, "maxIndex=%ld\n", maxIndex);
1083
fclose(localVar[thrId].fp2);*/
1089
void InitGame(int gameNo, int moveTreeFlag, int first, int handRelFirst, int thrId) {
1091
int k, s, h, m, ord, r;
1092
unsigned int topBitRank=1;
1093
unsigned short int ind;
1096
localVar[thrId].fp2=fopen("stat.txt","w");
1100
if (!suppressTTlog) {
1101
localVar[thrId].fp7=fopen("storett.txt","w");
1102
localVar[thrId].fp11=fopen("rectt.txt", "w");
1103
fclose(localVar[thrId].fp11);
1109
if (localVar[thrId].newDeal) {
1111
/* Initialization of the rel structure is implemented
1112
according to a solution given by Thomas Andrews */
1114
for (k=0; k<=3; k++)
1115
for (m=0; m<=3; m++)
1116
localVar[thrId].iniPosition.rankInSuit[k][m]=localVar[thrId].game.suit[k][m];
1118
for (s=0; s<4; s++) {
1119
localVar[thrId].rel[0].aggrRanks[s]=0;
1120
localVar[thrId].rel[0].winMask[s]=0;
1121
for (ord=1; ord<=13; ord++) {
1122
localVar[thrId].rel[0].absRank[ord][s].hand=-1;
1123
localVar[thrId].rel[0].absRank[ord][s].rank=0;
1125
for (r=2; r<=14; r++)
1126
localVar[thrId].rel[0].relRank[r][s]=0;
1129
for (ind=1; ind<8192; ind++) {
1130
if (ind>=(topBitRank+topBitRank)) {
1135
localVar[thrId].rel[ind]=localVar[thrId].rel[ind ^ topBitRank];
1137
for (s=0; s<4; s++) {
1139
for (r=14; r>=2; r--) {
1140
if ((ind & bitMapRank[r])!=0) {
1142
localVar[thrId].rel[ind].relRank[r][s]=ord;
1143
for (h=0; h<4; h++) {
1144
if ((localVar[thrId].game.suit[h][s] & bitMapRank[r])!=0) {
1145
localVar[thrId].rel[ind].absRank[ord][s].hand=h;
1146
localVar[thrId].rel[ind].absRank[ord][s].rank=r;
1152
for (k=ord+1; k<=13; k++) {
1153
localVar[thrId].rel[ind].absRank[k][s].hand=-1;
1154
localVar[thrId].rel[ind].absRank[k][s].rank=0;
1156
for (h=0; h<4; h++) {
1157
if (localVar[thrId].game.suit[h][s] & topBitRank) {
1158
localVar[thrId].rel[ind].aggrRanks[s]=
1159
(localVar[thrId].rel[ind].aggrRanks[s]>>2)|(h<<24);
1160
localVar[thrId].rel[ind].winMask[s]=
1161
(localVar[thrId].rel[ind].winMask[s]>>2)|(3<<24);
1169
localVar[thrId].iniPosition.first[localVar[thrId].game.noOfCards-4]=first;
1170
localVar[thrId].iniPosition.handRelFirst=handRelFirst;
1171
localVar[thrId].lookAheadPos=localVar[thrId].iniPosition;
1173
localVar[thrId].estTricks[1]=6;
1174
localVar[thrId].estTricks[3]=6;
1175
localVar[thrId].estTricks[0]=7;
1176
localVar[thrId].estTricks[2]=7;
1179
fprintf(localVar[thrId].fp2, "Estimated tricks for hand to play:\n");
1180
fprintf(localVar[thrId].fp2, "hand=%d est tricks=%d\n",
1181
localVar[thrId].handToPlay, localVar[thrId].estTricks[localVar[thrId].handToPlay]);
1184
InitSearch(&localVar[thrId].lookAheadPos, localVar[thrId].game.noOfCards-4,
1185
localVar[thrId].initialMoves, first, moveTreeFlag, thrId);
1190
void InitSearch(struct pos * posPoint, int depth, struct moveType startMoves[],
1191
int first, int mtd, int thrId) {
1193
int s, d, h, handRelFirst, maxAgg, maxHand=0;
1194
int k, noOfStartMoves; /* Number of start moves in the 1st trick */
1195
int hand[3], suit[3], rank[3];
1196
struct moveType move;
1197
unsigned short int startMovesBitMap[4][4]; /* Indices are hand and suit */
1198
unsigned short int aggHand[4][4];
1200
for (h=0; h<=3; h++)
1201
for (s=0; s<=3; s++)
1202
startMovesBitMap[h][s]=0;
1204
handRelFirst=posPoint->handRelFirst;
1205
noOfStartMoves=handRelFirst;
1207
for (k=0; k<=2; k++) {
1208
hand[k]=handId(first, k);
1209
suit[k]=startMoves[k].suit;
1210
rank[k]=startMoves[k].rank;
1211
if (k<noOfStartMoves)
1212
startMovesBitMap[hand[k]][suit[k]]|=bitMapRank[rank[k]];
1215
for (d=0; d<=49; d++) {
1216
/*bestMove[d].suit=0;*/
1217
localVar[thrId].bestMove[d].rank=0;
1218
localVar[thrId].bestMoveTT[d].rank=0;
1219
/*bestMove[d].weight=0;
1220
bestMove[d].sequence=0; 0315 */
1223
if (((handId(first, handRelFirst))==0)||
1224
((handId(first, handRelFirst))==2)) {
1225
localVar[thrId].nodeTypeStore[0]=MAXNODE;
1226
localVar[thrId].nodeTypeStore[1]=MINNODE;
1227
localVar[thrId].nodeTypeStore[2]=MAXNODE;
1228
localVar[thrId].nodeTypeStore[3]=MINNODE;
1231
localVar[thrId].nodeTypeStore[0]=MINNODE;
1232
localVar[thrId].nodeTypeStore[1]=MAXNODE;
1233
localVar[thrId].nodeTypeStore[2]=MINNODE;
1234
localVar[thrId].nodeTypeStore[3]=MAXNODE;
1238
posPoint->first[depth]=first;
1239
posPoint->handRelFirst=k;
1240
assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
1241
posPoint->tricksMAX=0;
1244
posPoint->move[depth+k]=startMoves[k-1];
1245
move=startMoves[k-1];
1248
posPoint->high[depth+k]=first;
1251
localVar[thrId].movePly[depth+k].current=0;
1252
localVar[thrId].movePly[depth+k].last=0;
1253
localVar[thrId].movePly[depth+k].move[0].suit=startMoves[k-1].suit;
1254
localVar[thrId].movePly[depth+k].move[0].rank=startMoves[k-1].rank;
1255
if (k<noOfStartMoves) { /* If there is more than one start move */
1256
if (WinningMove(&startMoves[k-1], &move, localVar[thrId].trump, thrId)) {
1257
posPoint->move[depth+k].suit=startMoves[k-1].suit;
1258
posPoint->move[depth+k].rank=startMoves[k-1].rank;
1259
posPoint->high[depth+k]=handId(first, noOfStartMoves-k);
1260
move=posPoint->move[depth+k];
1263
posPoint->move[depth+k]=posPoint->move[depth+k+1];
1264
posPoint->high[depth+k]=posPoint->high[depth+k+1];
1270
for (s=0; s<=3; s++)
1271
posPoint->removedRanks[s]=0;
1273
for (s=0; s<=3; s++) /* Suit */
1274
for (h=0; h<=3; h++) /* Hand */
1275
posPoint->removedRanks[s]|=
1276
posPoint->rankInSuit[h][s];
1277
for (s=0; s<=3; s++)
1278
posPoint->removedRanks[s]=~(posPoint->removedRanks[s]);
1280
for (s=0; s<=3; s++) /* Suit */
1281
for (h=0; h<=3; h++) /* Hand */
1282
posPoint->removedRanks[s]&=
1283
(~startMovesBitMap[h][s]);
1285
for (s=0; s<=3; s++)
1286
localVar[thrId].iniRemovedRanks[s]=posPoint->removedRanks[s];
1288
/*for (d=0; d<=49; d++) {
1289
for (s=0; s<=3; s++)
1290
posPoint->winRanks[d][s]=0;
1293
/* Initialize winning and second best ranks */
1294
for (s=0; s<=3; s++) {
1296
for (h=0; h<=3; h++) {
1297
aggHand[h][s]=startMovesBitMap[h][s] | localVar[thrId].game.suit[h][s];
1298
if (aggHand[h][s]>maxAgg) {
1299
maxAgg=aggHand[h][s];
1304
posPoint->winner[s].hand=maxHand;
1305
k=highestRank[aggHand[maxHand][s]];
1306
posPoint->winner[s].rank=k;
1309
for (h=0; h<=3; h++) {
1310
aggHand[h][s]&=(~bitMapRank[k]);
1311
if (aggHand[h][s]>maxAgg) {
1312
maxAgg=aggHand[h][s];
1317
posPoint->secondBest[s].hand=maxHand;
1318
posPoint->secondBest[s].rank=highestRank[aggHand[maxHand][s]];
1321
posPoint->secondBest[s].hand=-1;
1322
posPoint->secondBest[s].rank=0;
1326
posPoint->winner[s].hand=-1;
1327
posPoint->winner[s].rank=0;
1328
posPoint->secondBest[s].hand=-1;
1329
posPoint->secondBest[s].rank=0;
1334
for (s=0; s<=3; s++)
1335
for (h=0; h<=3; h++)
1336
posPoint->length[h][s]=
1337
(unsigned char)counttable[posPoint->rankInSuit[h][s]];
1340
for (d=0; d<=49; d++) {
1343
c1[d]=0; c2[d]=0; c3[d]=0; c4[d]=0; c5[d]=0; c6[d]=0; c7[d]=0;
1345
localVar[thrId].no[d]=0;
1350
localVar[thrId].lenSetSize=0;
1351
for (k=0; k<=13; k++) {
1352
for (h=0; h<=3; h++) {
1353
localVar[thrId].rootnp[k][h]=&localVar[thrId].posSearch[localVar[thrId].lenSetSize];
1354
localVar[thrId].posSearch[localVar[thrId].lenSetSize].suitLengths=0;
1355
localVar[thrId].posSearch[localVar[thrId].lenSetSize].posSearchPoint=NULL;
1356
localVar[thrId].posSearch[localVar[thrId].lenSetSize].left=NULL;
1357
localVar[thrId].posSearch[localVar[thrId].lenSetSize].right=NULL;
1358
localVar[thrId].lenSetSize++;
1361
localVar[thrId].nodeSetSize=0;
1362
localVar[thrId].winSetSize=0;
1374
int score1Counts[50], score0Counts[50];
1375
int sumScore1Counts, sumScore0Counts, dd, suit, rank, order;
1376
int c1[50], c2[50], c3[50], c4[50], c5[50], c6[50], c7[50], c8[50], c9[50];
1377
int sumc1, sumc2, sumc3, sumc4, sumc5, sumc6, sumc7, sumc8, sumc9;
1380
int ABsearch(struct pos * posPoint, int target, int depth, int thrId) {
1381
/* posPoint points to the current look-ahead position,
1382
target is number of tricks to take for the player,
1383
depth is the remaining search length, must be positive,
1384
the value of the subtree is returned. */
1386
int moveExists, mexists, value, hand, scoreFlag, found, trump;
1387
int ready, hfirst, hh, ss, rr, mcurrent, qtricks, tricks, res, k;
1388
unsigned short int makeWinRank[4];
1389
struct nodeCardsType * cardsP;
1390
struct evalType evalData;
1391
struct winCardType * np;
1392
struct posSearchType * pp;
1393
struct nodeCardsType * tempP;
1394
struct movePlyType *mply;
1395
unsigned short int aggr[4];
1396
unsigned short int ranks;
1397
long long suitLengths;
1399
struct evalType Evaluate(struct pos * posPoint, int trump, int thrId);
1400
void Make(struct pos * posPoint, unsigned short int trickCards[4],
1401
int depth, int trump, struct movePlyType *mply, int thrId);
1402
void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId);
1405
assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
1406
trump=localVar[thrId].trump;
1407
hand=handId(posPoint->first[depth], posPoint->handRelFirst);
1408
localVar[thrId].nodes++;
1409
if (posPoint->handRelFirst==0) {
1410
localVar[thrId].trickNodes++;
1411
if (posPoint->tricksMAX>=target) {
1412
for (ss=0; ss<=3; ss++)
1413
posPoint->winRanks[depth][ss]=0;
1418
score1Counts[depth]++;
1419
if (depth==localVar[thrId].iniDepth) {
1420
fprintf(localVar[thrId].fp2, "score statistics:\n");
1421
for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1422
fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1423
score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],
1425
fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1426
c6[dd], c7[dd], c8[dd]);
1433
if (((posPoint->tricksMAX+(depth>>2)+1)<target)/*&&(depth>0)*/) {
1434
for (ss=0; ss<=3; ss++)
1435
posPoint->winRanks[depth][ss]=0;
1439
score0Counts[depth]++;
1440
if (depth==localVar[thrId].iniDepth) {
1441
fprintf(localVar[thrId].fp2, "score statistics:\n");
1442
for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1443
fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1444
score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],
1446
fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1447
c6[dd], c7[dd], c8[dd]);
1455
if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) {
1456
qtricks=QuickTricks(posPoint, hand, depth, target, trump, &res, thrId);
1464
score1Counts[depth]++;
1465
if (depth==localVar[thrId].iniDepth) {
1466
fprintf(localVar[thrId].fp2, "score statistics:\n");
1467
for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1468
fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1469
score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],
1471
fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1472
c6[dd], c7[dd], c8[dd]);
1477
if (!LaterTricksMIN(posPoint,hand,depth,target,trump,thrId))
1481
qtricks=QuickTricks(posPoint, hand, depth, target, trump, &res, thrId);
1489
score0Counts[depth]++;
1490
if (depth==localVar[thrId].iniDepth) {
1491
fprintf(localVar[thrId].fp2, "score statistics:\n");
1492
for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1493
fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1494
score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],
1496
fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1497
c6[dd], c7[dd], c8[dd]);
1502
if (LaterTricksMAX(posPoint,hand,depth,target,trump,thrId))
1507
else if (posPoint->handRelFirst==1) {
1508
ss=posPoint->move[depth+1].suit;
1509
ranks=posPoint->rankInSuit[hand][ss] |
1510
posPoint->rankInSuit[partner[hand]][ss];
1511
found=FALSE; rr=0; qtricks=0;
1513
if ((trump!=4) && (ss!=trump) &&
1514
(((posPoint->rankInSuit[hand][ss]==0)
1515
&& (posPoint->rankInSuit[hand][trump]!=0))||
1516
((posPoint->rankInSuit[partner[hand]][ss]==0)
1517
&& (posPoint->rankInSuit[partner[hand]][trump]!=0)))) {
1518
/* Own side can ruff */
1519
if ((posPoint->rankInSuit[lho[hand]][ss]!=0)||
1520
(posPoint->rankInSuit[lho[hand]][trump]==0)) {
1526
else if ( ranks >(bitMapRank[posPoint->move[depth+1].rank] |
1527
posPoint->rankInSuit[lho[hand]][ss])) {
1528
/* Own side has highest card in suit */
1529
if ((trump==4) || ((ss==trump)||
1530
(posPoint->rankInSuit[lho[hand]][trump]==0)
1531
|| (posPoint->rankInSuit[lho[hand]][ss]!=0))) {
1532
rr=highestRank[ranks];
1542
if ((found)&&(depth!=localVar[thrId].iniDepth)) {
1543
for (k=0; k<=3; k++)
1544
posPoint->winRanks[depth][k]=0;
1546
posPoint->winRanks[depth][ss]=bitMapRank[rr];
1548
if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) {
1549
if (posPoint->tricksMAX+qtricks>=target) {
1552
else if (trump==4) {
1553
if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss])
1554
hh=hand; /* Hand to lead next trick */
1558
if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&&
1559
(posPoint->secondBest[ss].hand==hh)) {
1561
posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank];
1562
if (posPoint->tricksMAX+qtricks>=target) {
1567
for (k=0; k<=3; k++) {
1568
if ((k!=ss)&&(posPoint->length[hh][k]!=0)) { /* Not lead suit, not void in suit */
1569
if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0)
1570
&&(posPoint->length[partner[hh]][k]==0)) {
1571
qtricks+=counttable[posPoint->rankInSuit[hh][k]];
1572
if (posPoint->tricksMAX+qtricks>=target) {
1576
else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) {
1578
posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank];
1579
if (posPoint->tricksMAX+qtricks>=target) {
1589
if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) {
1592
else if (trump==4) {
1593
if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss])
1594
hh=hand; /* Hand to lead next trick */
1598
if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&&
1599
(posPoint->secondBest[ss].hand==hh)) {
1601
posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank];
1602
if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) {
1607
for (k=0; k<=3; k++) {
1608
if ((k!=ss)&&(posPoint->length[hh][k]!=0)) { /* Not lead suit, not void in suit */
1609
if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0)
1610
&&(posPoint->length[partner[hh]][k]==0)) {
1611
qtricks+=counttable[posPoint->rankInSuit[hh][k]];
1612
if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) {
1616
else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) {
1618
posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank];
1619
if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) {
1630
if ((posPoint->handRelFirst==0)&&
1631
(depth!=localVar[thrId].iniDepth)) {
1632
for (ss=0; ss<=3; ss++) {
1634
for (hh=0; hh<=3; hh++)
1635
aggr[ss]|=posPoint->rankInSuit[hh][ss];
1636
posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss];
1640
for (ss=0; ss<=2; ss++)
1641
for (hh=0; hh<=3; hh++) {
1643
suitLengths|=posPoint->length[hh][ss];
1646
pp=SearchLenAndInsert(localVar[thrId].rootnp[tricks][hand],
1647
suitLengths, FALSE, &res, thrId);
1648
/* Find node that fits the suit lengths */
1650
np=pp->posSearchPoint;
1654
cardsP=FindSOP(posPoint, np, hand, target, tricks, &scoreFlag, thrId);
1658
for (ss=0; ss<=3; ss++)
1659
posPoint->winRanks[depth][ss]=
1660
localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)cardsP->leastWin[ss]];
1662
if (cardsP->bestMoveRank!=0) {
1663
localVar[thrId].bestMoveTT[depth].suit=cardsP->bestMoveSuit;
1664
localVar[thrId].bestMoveTT[depth].rank=cardsP->bestMoveRank;
1669
score1Counts[depth]++;
1671
score0Counts[depth]++;
1672
if (depth==localVar[thrId].iniDepth) {
1673
fprintf(localVar[thrId].fp2, "score statistics:\n");
1674
for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1675
fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1676
score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],c3[dd], c4[dd]);
1677
fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1678
c6[dd], c7[dd], c8[dd]);
1683
if (!suppressTTlog) {
1684
if (lastTTstore<SEARCHSIZE)
1685
ReceiveTTstore(posPoint, cardsP, target, depth, thrId);
1693
for (ss=0; ss<=3; ss++)
1694
posPoint->winRanks[depth][ss]=
1695
localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)cardsP->leastWin[ss]];
1697
if (cardsP->bestMoveRank!=0) {
1698
localVar[thrId].bestMoveTT[depth].suit=cardsP->bestMoveSuit;
1699
localVar[thrId].bestMoveTT[depth].rank=cardsP->bestMoveRank;
1704
score1Counts[depth]++;
1706
score0Counts[depth]++;
1707
if (depth==localVar[thrId].iniDepth) {
1708
fprintf(localVar[thrId].fp2, "score statistics:\n");
1709
for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1710
fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1711
score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd],
1713
fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1714
c6[dd], c7[dd], c8[dd]);
1720
if (!suppressTTlog) {
1721
if (lastTTstore<SEARCHSIZE)
1722
ReceiveTTstore(posPoint, cardsP, target, depth, thrId);
1733
if (depth==0) { /* Maximum depth? */
1734
evalData=Evaluate(posPoint, trump, thrId); /* Leaf node */
1735
if (evalData.tricks>=target)
1739
for (ss=0; ss<=3; ss++) {
1740
posPoint->winRanks[depth][ss]=evalData.winRanks[ss];
1745
score1Counts[depth]++;
1747
score0Counts[depth]++;
1748
if (depth==localVar[thrId].iniDepth) {
1749
fprintf(localVar[thrId].fp2, "score statistics:\n");
1750
for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
1751
fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
1752
score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd],
1754
fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd],
1755
c6[dd], c7[dd], c8[dd]);
1763
mply=&localVar[thrId].movePly[depth];
1764
moveExists=MoveGen(posPoint, depth, trump, mply, thrId);
1767
if ((posPoint->handRelFirst==3)&&(depth>=/*29*/33/*37*/)
1768
&&(depth!=localVar[thrId].iniDepth)) {
1769
/*localVar[thrId].movePly[depth].current=0;*/
1774
Make(posPoint, makeWinRank, depth, trump, mply, thrId);
1777
for (ss=0; ss<=3; ss++) {
1779
for (hh=0; hh<=3; hh++)
1780
aggr[ss]|=posPoint->rankInSuit[hh][ss];
1781
posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss];
1784
hfirst=posPoint->first[depth];
1786
for (ss=0; ss<=2; ss++)
1787
for (hh=0; hh<=3; hh++) {
1789
suitLengths|=posPoint->length[hh][ss];
1792
pp=SearchLenAndInsert(localVar[thrId].rootnp[tricks][hfirst],
1793
suitLengths, FALSE, &res, thrId);
1794
/* Find node that fits the suit lengths */
1796
np=pp->posSearchPoint;
1800
tempP=FindSOP(posPoint, np, hfirst, target, tricks, &scoreFlag, thrId);
1803
if ((localVar[thrId].nodeTypeStore[hand]==MAXNODE)&&(scoreFlag==1)) {
1804
for (ss=0; ss<=3; ss++)
1805
posPoint->winRanks[depth+1][ss]=
1806
localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)tempP->leastWin[ss]];
1807
if (tempP->bestMoveRank!=0) {
1808
localVar[thrId].bestMoveTT[depth+1].suit=tempP->bestMoveSuit;
1809
localVar[thrId].bestMoveTT[depth+1].rank=tempP->bestMoveRank;
1811
for (ss=0; ss<=3; ss++)
1812
posPoint->winRanks[depth+1][ss]|=makeWinRank[ss];
1813
Undo(posPoint, depth+1, &localVar[thrId].movePly[depth+1],thrId);
1816
else if ((localVar[thrId].nodeTypeStore[hand]==MINNODE)&&(scoreFlag==0)) {
1817
for (ss=0; ss<=3; ss++)
1818
posPoint->winRanks[depth+1][ss]=
1819
localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)tempP->leastWin[ss]];
1820
if (tempP->bestMoveRank!=0) {
1821
localVar[thrId].bestMoveTT[depth+1].suit=tempP->bestMoveSuit;
1822
localVar[thrId].bestMoveTT[depth+1].rank=tempP->bestMoveRank;
1824
for (ss=0; ss<=3; ss++)
1825
posPoint->winRanks[depth+1][ss]|=makeWinRank[ss];
1826
Undo(posPoint, depth+1, &localVar[thrId].movePly[depth+1], thrId);
1830
localVar[thrId].movePly[depth+1].move[localVar[thrId].movePly[depth+1].current].weight+=100;
1836
Undo(posPoint, depth, mply, thrId);
1840
if (mply->current <= (mply->last-1)) {
1848
MergeSort(mply->last+1, mply->move);
1854
if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) {
1856
for (ss=0; ss<=3; ss++)
1857
posPoint->winRanks[depth][ss]=0;
1859
while (moveExists) {
1860
Make(posPoint, makeWinRank, depth, trump, mply, thrId); /* Make current move */
1862
assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
1863
value=ABsearch(posPoint, target, depth-1, thrId);
1865
Undo(posPoint, depth, mply, thrId); /* Retract current move */
1868
for (ss=0; ss<=3; ss++)
1869
posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] |
1871
mcurrent=mply->current;
1872
localVar[thrId].bestMove[depth]=mply->move[mcurrent];
1875
for (ss=0; ss<=3; ss++)
1876
posPoint->winRanks[depth][ss]=posPoint->winRanks[depth][ss] |
1877
posPoint->winRanks[depth-1][ss] | makeWinRank[ss];
1879
moveExists=NextMove(posPoint, depth, mply, thrId);
1882
else { /* A minnode */
1884
for (ss=0; ss<=3; ss++)
1885
posPoint->winRanks[depth][ss]=0;
1887
while (moveExists) {
1888
Make(posPoint, makeWinRank, depth, trump, mply, thrId); /* Make current move */
1890
value=ABsearch(posPoint, target, depth-1, thrId);
1892
Undo(posPoint, depth, mply, thrId); /* Retract current move */
1895
for (ss=0; ss<=3; ss++)
1896
posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] |
1898
mcurrent=mply->current;
1899
localVar[thrId].bestMove[depth]=mply->move[mcurrent];
1902
for (ss=0; ss<=3; ss++)
1903
posPoint->winRanks[depth][ss]=posPoint->winRanks[depth][ss] |
1904
posPoint->winRanks[depth-1][ss] | makeWinRank[ss];
1906
moveExists=NextMove(posPoint, depth, mply, thrId);
1912
if(posPoint->handRelFirst==0) {
1918
if (depth!=localVar[thrId].iniDepth)
1919
BuildSOP(posPoint, tricks, hand, target, depth,
1921
if (localVar[thrId].clearTTflag) {
1922
/* Wipe out the TT dynamically allocated structures
1923
except for the initially allocated structures.
1924
Set the TT limits to the initial values.
1925
Reset TT array indices to zero.
1926
Reset memory chunk indices to zero.
1927
Set allocated memory to the initial value. */
1928
/*localVar[thrId].fp2=fopen("dyn.txt", "a");
1929
fprintf(localVar[thrId].fp2, "Clear TT:\n");
1930
fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n",
1931
wcount, ncount, lcount);
1932
fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n",
1933
winSetSize, nodeSetSize, lenSetSize);
1934
fprintf(localVar[thrId].fp2, "\n");
1935
fclose(localVar[thrId].fp2);*/
1938
localVar[thrId].winSetSizeLimit=WINIT;
1939
localVar[thrId].nodeSetSizeLimit=NINIT;
1940
localVar[thrId].lenSetSizeLimit=LINIT;
1941
localVar[thrId].lcount=0;
1942
localVar[thrId].allocmem=(localVar[thrId].lenSetSizeLimit+1)*sizeof(struct posSearchType);
1943
localVar[thrId].lenSetSize=0;
1944
localVar[thrId].posSearch=localVar[thrId].pl[localVar[thrId].lcount];
1945
for (k=0; k<=13; k++) {
1946
for (hh=0; hh<=3; hh++) {
1947
localVar[thrId].rootnp[k][hh]=&localVar[thrId].posSearch[localVar[thrId].lenSetSize];
1948
localVar[thrId].posSearch[localVar[thrId].lenSetSize].suitLengths=0;
1949
localVar[thrId].posSearch[localVar[thrId].lenSetSize].posSearchPoint=NULL;
1950
localVar[thrId].posSearch[localVar[thrId].lenSetSize].left=NULL;
1951
localVar[thrId].posSearch[localVar[thrId].lenSetSize].right=NULL;
1952
localVar[thrId].lenSetSize++;
1955
localVar[thrId].nodeSetSize=0;
1956
localVar[thrId].winSetSize=0;
1957
localVar[thrId].wcount=0; localVar[thrId].ncount=0;
1958
localVar[thrId].allocmem+=(localVar[thrId].winSetSizeLimit+1)*sizeof(struct winCardType);
1959
localVar[thrId].winCards=localVar[thrId].pw[localVar[thrId].wcount];
1960
localVar[thrId].allocmem+=(localVar[thrId].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType);
1961
localVar[thrId].nodeCards=localVar[thrId].pn[localVar[thrId].ncount];
1962
localVar[thrId].clearTTflag=FALSE;
1963
localVar[thrId].windex=-1;
1971
score1Counts[depth]++;
1973
score0Counts[depth]++;
1974
if (depth==localVar[thrId].iniDepth) {
1975
if (localVar[thrId].fp2==NULL)
1977
fprintf(localVar[thrId].fp2, "\n");
1978
fprintf(localVar[thrId].fp2, "top level cards:\n");
1979
for (hh=0; hh<=3; hh++) {
1980
fprintf(localVar[thrId].fp2, "hand=%c\n", cardHand[hh]);
1981
for (ss=0; ss<=3; ss++) {
1982
fprintf(localVar[thrId].fp2, "suit=%c", cardSuit[ss]);
1983
for (rr=14; rr>=2; rr--)
1984
if (posPoint->rankInSuit[hh][ss] & bitMapRank[rr])
1985
fprintf(localVar[thrId].fp2, " %c", cardRank[rr]);
1986
fprintf(localVar[thrId].fp2, "\n");
1988
fprintf(localVar[thrId].fp2, "\n");
1990
fprintf(localVar[thrId].fp2, "top level winning cards:\n");
1991
for (ss=0; ss<=3; ss++) {
1992
fprintf(localVar[thrId].fp2, "suit=%c", cardSuit[ss]);
1993
for (rr=14; rr>=2; rr--)
1994
if (posPoint->winRanks[depth][ss] & bitMapRank[rr])
1995
fprintf(localVar[thrId].fp2, " %c", cardRank[rr]);
1996
fprintf(localVar[thrId].fp2, "\n");
1998
fprintf(localVar[thrId].fp2, "\n");
1999
fprintf(localVar[thrId].fp2, "\n");
2001
fprintf(localVar[thrId].fp2, "score statistics:\n");
2004
sumc1=0; sumc2=0; sumc3=0; sumc4=0;
2005
sumc5=0; sumc6=0; sumc7=0; sumc8=0; sumc9=0;
2006
for (dd=localVar[thrId].iniDepth; dd>=0; dd--) {
2007
fprintf(localVar[thrId].fp2, "depth=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd,
2008
score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], c4[dd]);
2009
fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd],
2011
sumScore0Counts=sumScore0Counts+score0Counts[dd];
2012
sumScore1Counts=sumScore1Counts+score1Counts[dd];
2023
fprintf(localVar[thrId].fp2, "\n");
2024
fprintf(localVar[thrId].fp2, "score sum statistics:\n");
2025
fprintf(localVar[thrId].fp2, "\n");
2026
fprintf(localVar[thrId].fp2, "sumScore0Counts=%d sumScore1Counts=%d\n",
2027
sumScore0Counts, sumScore1Counts);
2028
fprintf(localVar[thrId].fp2, "nodeSetSize=%d winSetSize=%d\n", localVar[thrId].nodeSetSize,
2029
localVar[thrId].winSetSize);
2030
fprintf(localVar[thrId].fp2, "sumc1=%d sumc2=%d sumc3=%d sumc4=%d\n",
2031
sumc1, sumc2, sumc3, sumc4);
2032
fprintf(localVar[thrId].fp2, "sumc5=%d sumc6=%d sumc7=%d sumc8=%d sumc9=%d\n",
2033
sumc5, sumc6, sumc7, sumc8, sumc9);
2034
fprintf(localVar[thrId].fp2, "\n");
2035
fprintf(localVar[thrId].fp2, "\n");
2036
fprintf(localVar[thrId].fp2, "No of searched nodes per depth:\n");
2037
for (dd=localVar[thrId].iniDepth; dd>=0; dd--)
2038
fprintf(localVar[thrId].fp2, "depth=%d nodes=%d\n", dd, localVar[thrId].no[dd]);
2039
fprintf(localVar[thrId].fp2, "\n");
2040
fprintf(localVar[thrId].fp2, "Total nodes=%d\n", localVar[thrId].nodes);
2048
void Make(struct pos * posPoint, unsigned short int trickCards[4],
2049
int depth, int trump, struct movePlyType *mply, int thrId) {
2050
int r, s, t, u, w, firstHand;
2051
int suit, count, mcurr, h, q, done;
2052
struct moveType mo1, mo2;
2053
unsigned short aggr;
2055
assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
2056
for (suit=0; suit<=3; suit++)
2059
firstHand=posPoint->first[depth];
2062
if (posPoint->handRelFirst==3) { /* This hand is last hand */
2064
mo2=posPoint->move[depth+1];
2065
if (mo1.suit==mo2.suit) {
2066
if (mo1.rank>mo2.rank) {
2067
posPoint->move[depth]=mo1;
2068
posPoint->high[depth]=handId(firstHand, 3);
2071
posPoint->move[depth]=posPoint->move[depth+1];
2072
posPoint->high[depth]=posPoint->high[depth+1];
2075
else if (mo1.suit==trump) {
2076
posPoint->move[depth]=mo1;
2077
posPoint->high[depth]=handId(firstHand, 3);
2080
posPoint->move[depth]=posPoint->move[depth+1];
2081
posPoint->high[depth]=posPoint->high[depth+1];
2084
/* Is the trick won by rank? */
2085
suit=posPoint->move[depth].suit;
2087
mcurr=mply->current;
2088
if (mply->move[mcurr].suit==suit)
2090
for (h=1; h<=3; h++) {
2091
mcurr=localVar[thrId].movePly[depth+h].current;
2092
if (localVar[thrId].movePly[depth+h].move[mcurr].suit==suit)
2096
if (localVar[thrId].nodeTypeStore[posPoint->high[depth]]==MAXNODE)
2097
posPoint->tricksMAX++;
2098
posPoint->first[depth-1]=posPoint->high[depth]; /* Defines who is first
2101
t=handId(firstHand, 3);
2102
posPoint->handRelFirst=0; /* Hand pointed to by posPoint->first
2103
will lead the next trick */
2106
for (s=3; s>=0; s--) {
2107
q=handId(firstHand, 3-s);
2108
/* Add the moves to removed ranks */
2109
r=localVar[thrId].movePly[depth+s].current;
2110
w=localVar[thrId].movePly[depth+s].move[r].rank;
2111
u=localVar[thrId].movePly[depth+s].move[r].suit;
2112
posPoint->removedRanks[u]|=bitMapRank[w];
2115
posPoint->rankInSuit[t][u]&=(~bitMapRank[w]);
2117
if ((w==posPoint->winner[u].rank)||(w==posPoint->secondBest[u].rank)) {
2119
for (h=0; h<=3; h++)
2120
aggr|=posPoint->rankInSuit[h][u];
2121
posPoint->winner[u].rank=localVar[thrId].rel[aggr].absRank[1][u].rank;
2122
posPoint->winner[u].hand=localVar[thrId].rel[aggr].absRank[1][u].hand;
2123
posPoint->secondBest[u].rank=localVar[thrId].rel[aggr].absRank[2][u].rank;
2124
posPoint->secondBest[u].hand=localVar[thrId].rel[aggr].absRank[2][u].hand;
2127
/* Determine win-ranked cards */
2128
if ((q==posPoint->high[depth])&&(!done)) {
2131
trickCards[u]=bitMapRank[w];
2132
/* Mark ranks as winning if they are part of a sequence */
2133
trickCards[u]|=localVar[thrId].movePly[depth+s].move[r].sequence;
2138
else if (posPoint->handRelFirst==0) { /* Is it the 1st hand? */
2139
posPoint->first[depth-1]=firstHand; /* First hand is not changed in
2141
posPoint->high[depth]=firstHand;
2142
posPoint->move[depth]=mply->move[r];
2144
posPoint->handRelFirst=1;
2146
u=mply->move[r].suit;
2147
w=mply->move[r].rank;
2148
posPoint->rankInSuit[t][u]&=(~bitMapRank[w]);
2152
mo2=posPoint->move[depth+1];
2154
u=mply->move[r].suit;
2155
w=mply->move[r].rank;
2156
if (mo1.suit==mo2.suit) {
2157
if (mo1.rank>mo2.rank) {
2158
posPoint->move[depth]=mo1;
2159
posPoint->high[depth]=handId(firstHand, posPoint->handRelFirst);
2162
posPoint->move[depth]=posPoint->move[depth+1];
2163
posPoint->high[depth]=posPoint->high[depth+1];
2166
else if (mo1.suit==trump) {
2167
posPoint->move[depth]=mo1;
2168
posPoint->high[depth]=handId(firstHand, posPoint->handRelFirst);
2171
posPoint->move[depth]=posPoint->move[depth+1];
2172
posPoint->high[depth]=posPoint->high[depth+1];
2175
t=handId(firstHand, posPoint->handRelFirst);
2176
posPoint->handRelFirst++; /* Current hand is stepped */
2177
assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
2178
posPoint->first[depth-1]=firstHand; /* First hand is not changed in
2181
posPoint->rankInSuit[t][u]&=(~bitMapRank[w]);
2184
posPoint->length[t][u]--;
2187
localVar[thrId].no[depth]++;
2194
void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId) {
2195
int r, s, t, u, w, firstHand;
2197
assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3));
2199
firstHand=posPoint->first[depth];
2201
switch (posPoint->handRelFirst) {
2202
case 3: case 2: case 1:
2203
posPoint->handRelFirst--;
2206
posPoint->handRelFirst=3;
2209
if (posPoint->handRelFirst==0) { /* 1st hand which won the previous
2213
u=mply->move[r].suit;
2214
w=mply->move[r].rank;
2216
else if (posPoint->handRelFirst==3) { /* Last hand */
2217
for (s=3; s>=0; s--) {
2218
/* Delete the moves from removed ranks */
2219
r=localVar[thrId].movePly[depth+s].current;
2220
w=localVar[thrId].movePly[depth+s].move[r].rank;
2221
u=localVar[thrId].movePly[depth+s].move[r].suit;
2223
posPoint->removedRanks[u]&= (~bitMapRank[w]);
2225
if (w>posPoint->winner[u].rank) {
2226
posPoint->secondBest[u].rank=posPoint->winner[u].rank;
2227
posPoint->secondBest[u].hand=posPoint->winner[u].hand;
2228
posPoint->winner[u].rank=w;
2229
posPoint->winner[u].hand=handId(firstHand, 3-s);
2232
else if (w>posPoint->secondBest[u].rank) {
2233
posPoint->secondBest[u].rank=w;
2234
posPoint->secondBest[u].hand=handId(firstHand, 3-s);
2237
t=handId(firstHand, 3);
2240
if (localVar[thrId].nodeTypeStore[posPoint->first[depth-1]]==MAXNODE)
2241
/* First hand of next trick is winner of the current trick */
2242
posPoint->tricksMAX--;
2245
t=handId(firstHand, posPoint->handRelFirst);
2247
u=mply->move[r].suit;
2248
w=mply->move[r].rank;
2251
posPoint->rankInSuit[t][u]|=bitMapRank[w];
2253
posPoint->length[t][u]++;
2260
struct evalType Evaluate(struct pos * posPoint, int trump, int thrId) {
2261
int s, smax=0, max, k, firstHand, count;
2262
struct evalType eval;
2264
firstHand=posPoint->first[0];
2265
assert((firstHand >= 0)&&(firstHand <= 3));
2267
for (s=0; s<=3; s++)
2270
/* Who wins the last trick? */
2271
if (trump!=4) { /* Highest trump card wins */
2274
for (s=0; s<=3; s++) {
2275
if (posPoint->rankInSuit[s][trump]!=0)
2277
if (posPoint->rankInSuit[s][trump]>max) {
2279
max=posPoint->rankInSuit[s][trump];
2283
if (max>0) { /* Trumpcard wins */
2285
eval.winRanks[trump]=max;
2287
if (localVar[thrId].nodeTypeStore[smax]==MAXNODE)
2294
/* Who has the highest card in the suit played by 1st hand? */
2297
while (k<=3) { /* Find the card the 1st hand played */
2298
if (posPoint->rankInSuit[firstHand][k]!=0) /* Is this the card? */
2307
for (s=0; s<=3; s++) {
2308
if (posPoint->rankInSuit[s][k]!=0)
2310
if (posPoint->rankInSuit[s][k]>max) {
2312
max=posPoint->rankInSuit[s][k];
2317
eval.winRanks[k]=max;
2319
if (localVar[thrId].nodeTypeStore[smax]==MAXNODE)
2325
eval.tricks=posPoint->tricksMAX+1;
2329
eval.tricks=posPoint->tricksMAX;
2334
int QuickTricks(struct pos * posPoint, int hand,
2335
int depth, int target, int trump, int *result, int thrId) {
2336
int suit, sum, qtricks, commPartner, commRank=0, commSuit=-1, s, found=FALSE;
2338
int countLho, countRho, countPart, countOwn, lhoTrumpRanks, rhoTrumpRanks;
2339
int cutoff, ss, rr, lowestQtricks=0, count=0/*, ruff=FALSE*/;
2341
int QtricksLeadHandNT(int hand, struct pos *posPoint, int cutoff, int depth,
2342
int countLho, int countRho, int *lhoTrumpRanks, int *rhoTrumpRanks, int commPartner,
2343
int commSuit, int countOwn, int countPart, int suit, int qtricks, int trump, int *res);
2345
int QtricksLeadHandTrump(int hand, struct pos *posPoint, int cutoff, int depth,
2346
int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn,
2347
int countPart, int suit, int qtricks, int trump, int *res);
2349
int QuickTricksPartnerHandTrump(int hand, struct pos *posPoint, int cutoff, int depth,
2350
int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn,
2351
int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId);
2353
int QuickTricksPartnerHandNT(int hand, struct pos *posPoint, int cutoff, int depth,
2354
int countLho, int countRho, int countOwn,
2355
int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId);
2359
for (s=0; s<=3; s++)
2360
posPoint->winRanks[depth][s]=0;
2362
if ((depth<=0)||(depth==localVar[thrId].iniDepth)) {
2367
if (localVar[thrId].nodeTypeStore[hand]==MAXNODE)
2368
cutoff=target-posPoint->tricksMAX;
2370
cutoff=posPoint->tricksMAX-target+(depth>>2)+2;
2373
for (s=0; s<=3; s++) {
2374
if ((trump!=4)&&(trump!=s)) {
2375
if (posPoint->winner[s].hand==partner[hand]) {
2376
/* Partner has winning card */
2377
if (posPoint->rankInSuit[hand][s]!=0) {
2378
/* Own hand has card in suit */
2379
if (((posPoint->rankInSuit[lho[hand]][s]!=0) ||
2381
(posPoint->rankInSuit[lho[hand]][trump]==0))
2382
/* LHO has no trump */
2383
&& ((posPoint->rankInSuit[rho[hand]][s]!=0) ||
2385
(posPoint->rankInSuit[rho[hand]][trump]==0))) {
2386
/* RHO has no trump */
2389
commRank=posPoint->winner[s].rank;
2394
else if (posPoint->secondBest[s].hand==partner[hand]) {
2395
if ((posPoint->winner[s].hand==hand)&&
2396
(posPoint->length[hand][s]>=2)&&(posPoint->length[partner[hand]][s]>=2)) {
2397
if (((posPoint->rankInSuit[lho[hand]][s]!=0) ||
2398
(posPoint->rankInSuit[lho[hand]][trump]==0))
2399
&& ((posPoint->rankInSuit[rho[hand]][s]!=0) ||
2400
(posPoint->rankInSuit[rho[hand]][trump]==0))) {
2403
commRank=posPoint->secondBest[s].rank;
2409
else if (trump==4) {
2410
if (posPoint->winner[s].hand==partner[hand]) {
2411
/* Partner has winning card */
2412
if (posPoint->rankInSuit[hand][s]!=0) {
2413
/* Own hand has card in suit */
2416
commRank=posPoint->winner[s].rank;
2420
else if (posPoint->secondBest[s].hand==partner[hand]) {
2421
if ((posPoint->winner[s].hand==hand)&&
2422
(posPoint->length[hand][s]>=2)&&(posPoint->length[partner[hand]][s]>=2)) {
2425
commRank=posPoint->secondBest[s].rank;
2432
if ((trump!=4) && (!commPartner) &&
2433
(posPoint->rankInSuit[hand][trump]!=0) &&
2434
(posPoint->winner[trump].hand==partner[hand])) {
2437
commRank=posPoint->winner[trump].rank;
2443
lhoTrumpRanks=posPoint->length[lho[hand]][trump];
2444
rhoTrumpRanks=posPoint->length[rho[hand]][trump];
2450
countOwn=posPoint->length[hand][suit];
2451
countLho=posPoint->length[lho[hand]][suit];
2452
countRho=posPoint->length[rho[hand]][suit];
2453
countPart=posPoint->length[partner[hand]][suit];
2454
opps=countLho | countRho;
2456
if (!opps && (countPart==0)) {
2458
/* Continue with next suit. */
2459
if ((trump!=4)&&(trump!=suit)) {
2461
if ((trump!=4) && (suit==trump))
2465
if ((trump!=4) && (trump==suit)) {
2477
/* Long tricks when only leading hand have cards in the suit. */
2478
if ((trump!=4) && (trump!=suit)) {
2479
if ((lhoTrumpRanks==0) && (rhoTrumpRanks==0)) {
2481
if (qtricks>=cutoff)
2484
if ((trump!=4) && (suit==trump))
2490
if ((trump!=4) && (suit==trump))
2497
if (qtricks>=cutoff)
2500
if ((trump!=4) && (suit==trump)) {
2508
if ((trump!=4) && (suit==trump))
2515
if (!opps && (trump!=4) && (suit==trump)) {
2516
/* The partner but not the opponents have cards in the trump suit. */
2517
sum=Max(countOwn, countPart);
2518
for (s=0; s<=3; s++) {
2519
if ((sum>0)&&(s!=trump)&&(countOwn>=countPart)&&(posPoint->length[hand][s]>0)&&
2520
(posPoint->length[partner[hand]][s]==0)) {
2525
/* If the additional trick by ruffing causes a cutoff. (qtricks not incremented.) */
2530
/* The partner but not the opponents have cards in the suit. */
2531
sum=Min(countOwn,countPart);
2536
else if ((suit!=trump)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
2543
if (!opps && (countOwn==0)) {
2544
if ((trump!=4) && (trump!=suit)) {
2545
if ((lhoTrumpRanks==0) && (rhoTrumpRanks==0)) {
2547
posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
2548
if (qtricks>=cutoff)
2551
if ((trump!=4) && (suit==trump))
2557
if ((trump!=4) && (suit==trump))
2564
posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
2565
if (qtricks>=cutoff)
2567
if ((trump!=4) && (suit==trump)) {
2575
if ((trump!=4) && (suit==trump))
2582
if (!opps && (trump!=4) && (suit==trump)) {
2583
sum=Max(countOwn, countPart);
2584
for (s=0; s<=3; s++) {
2585
if ((sum>0)&&(s!=trump)&&(countOwn<=countPart)&&(posPoint->length[partner[hand]][s]>0)&&
2586
(posPoint->length[hand][s]==0)) {
2592
posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
2597
sum=Min(countOwn,countPart);
2602
else if ((suit!=trump)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
2611
if (posPoint->winner[suit].rank==0) {
2612
if ((trump!=4) && (suit==trump)) {
2620
if ((trump!=4) && (suit==trump))
2626
if (posPoint->winner[suit].hand==hand) {
2627
if ((trump!=4)&&(trump!=suit)) {
2628
qtricks=QtricksLeadHandTrump(hand, posPoint, cutoff, depth,
2629
countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, countOwn,
2630
countPart, suit, qtricks, trump, &res);
2635
if ((trump!=4) && (suit==trump))
2641
qtricks=QtricksLeadHandNT(hand, posPoint, cutoff, depth,
2642
countLho, countRho, &lhoTrumpRanks, &rhoTrumpRanks,
2643
commPartner, commSuit, countOwn,
2644
countPart, suit, qtricks, trump, &res);
2648
if ((trump!=4) && (trump==suit)) {
2661
/* It was not possible to take a quick trick by own winning card in
2664
/* Partner winning card? */
2665
if ((posPoint->winner[suit].hand==partner[hand])&&(1/*countPart>0*/)) {
2666
/* Winner found at partner*/
2668
/* There is communication with the partner */
2669
if ((trump!=4)&&(trump!=suit)) {
2670
qtricks=QuickTricksPartnerHandTrump(hand, posPoint, cutoff, depth,
2671
countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, countOwn,
2672
countPart, suit, qtricks, commSuit, commRank, trump, &res, thrId);
2677
if ((trump!=4) && (suit==trump))
2683
qtricks=QuickTricksPartnerHandNT(hand, posPoint, cutoff, depth,
2684
countLho, countRho, countOwn,
2685
countPart, suit, qtricks, commSuit, commRank, trump, &res, thrId);
2689
if ((trump!=4) && (trump==suit)) {
2703
if ((trump!=4) &&(suit!=trump)&&
2704
(countOwn>0)&&(lowestQtricks==0)&&
2705
((qtricks==0)||((posPoint->winner[suit].hand!=hand)&&
2706
(posPoint->winner[suit].hand!=partner[hand])&&
2707
(posPoint->winner[trump].hand!=hand)&&
2708
(posPoint->winner[trump].hand!=partner[hand])))) {
2709
if ((countPart==0)&&(posPoint->length[partner[hand]][trump]>0)) {
2710
if (((countRho>0)||(posPoint->length[rho[hand]][trump]==0))&&
2711
((countLho>0)||(posPoint->length[lho[hand]][trump]==0))) {
2716
if ((trump!=4) && (suit==trump))
2720
else if ((countRho==0)&&(countLho==0)) {
2721
if ((posPoint->rankInSuit[lho[hand]][trump] |
2722
posPoint->rankInSuit[rho[hand]][trump]) <
2723
posPoint->rankInSuit[partner[hand]][trump]) {
2726
rr=highestRank[posPoint->rankInSuit[partner[hand]][trump]];
2728
posPoint->winRanks[depth][trump]|=bitMapRank[rr];
2734
if ((trump!=4) && (suit==trump))
2738
else if (countLho==0) {
2739
if (posPoint->rankInSuit[lho[hand]][trump] <
2740
posPoint->rankInSuit[partner[hand]][trump]) {
2742
for (rr=14; rr>=2; rr--) {
2743
if ((posPoint->rankInSuit[partner[hand]][trump] &
2744
bitMapRank[rr])!=0) {
2745
posPoint->winRanks[depth][trump]|=bitMapRank[rr];
2753
if ((trump!=4) && (suit==trump))
2757
else if (countRho==0) {
2758
if (posPoint->rankInSuit[rho[hand]][trump] <
2759
posPoint->rankInSuit[partner[hand]][trump]) {
2761
for (rr=14; rr>=2; rr--) {
2762
if ((posPoint->rankInSuit[partner[hand]][trump] &
2763
bitMapRank[rr])!=0) {
2764
posPoint->winRanks[depth][trump]|=bitMapRank[rr];
2772
if ((trump!=4) && (suit==trump))
2778
if (qtricks>=cutoff)
2780
if ((trump!=4) && (suit==trump)) {
2788
if ((trump!=4) && (suit==trump))
2795
if ((trump==4)||(posPoint->winner[trump].hand==-1)) {
2796
for (ss=0; ss<=3; ss++) {
2797
if (posPoint->winner[ss].hand==-1)
2799
if (posPoint->length[hand][ss]>0) {
2800
posPoint->winRanks[depth][ss]=
2801
bitMapRank[posPoint->winner[ss].rank];
2804
if (localVar[thrId].nodeTypeStore[hand]!=MAXNODE)
2805
cutoff=target-posPoint->tricksMAX;
2807
cutoff=posPoint->tricksMAX-target+(depth>>2)+2;
2820
int QtricksLeadHandTrump(int hand, struct pos *posPoint, int cutoff, int depth,
2821
int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn,
2822
int countPart, int suit, int qtricks, int trump, int *res) {
2823
/* res=0 Continue with same suit.
2825
res=2 Continue with next suit. */
2831
if (((countLho!=0) || (lhoTrumpRanks==0)) && ((countRho!=0) || (rhoTrumpRanks==0))) {
2832
posPoint->winRanks[depth][suit]|=
2833
bitMapRank[posPoint->winner[suit].rank];
2838
if ((countLho<=1)&&(countRho<=1)&&(countPart<=1)&&
2839
(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
2848
if (posPoint->secondBest[suit].hand==hand) {
2849
if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
2850
posPoint->winRanks[depth][suit]|=
2851
bitMapRank[posPoint->secondBest[suit].rank];
2855
if ((countLho<=2)&&(countRho<=2)&&(countPart<=2)) {
2864
for (k=0; k<=3; k++)
2865
aggr|=posPoint->rankInSuit[k][suit];
2866
if (rel[aggr].absRank[3][suit].hand==hand) {
2868
posPoint->winRanks[depth][suit]|=
2869
bitMapRank[rel[aggr].absRank[3][suit].rank];
2872
if ((countLho<=3)&&(countRho<=3)&&(countPart<=3)) {
2883
else if ((posPoint->secondBest[suit].hand==partner[hand])
2884
&&(countOwn>1)&&(countPart>1)) {
2885
/* Second best at partner and suit length of own
2886
hand and partner > 1 */
2887
if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
2888
posPoint->winRanks[depth][suit]|=
2889
bitMapRank[posPoint->secondBest[suit].rank];
2893
if ((countLho<=2)&&(countRho<=2)&&((countPart<=2)||(countOwn<=2))) {
2894
qt+=Max(countOwn-2, countPart-2);
2906
int QtricksLeadHandNT(int hand, struct pos *posPoint, int cutoff, int depth,
2907
int countLho, int countRho, int *lhoTrumpRanks, int *rhoTrumpRanks,
2908
int commPartner, int commSuit, int countOwn,
2909
int countPart, int suit, int qtricks, int trump, int *res) {
2910
/* res=0 Continue with same suit.
2912
res=2 Continue with next suit. */
2918
posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank];
2922
if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) {
2923
/*if (trump==suit) {*/
2924
(*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1);
2925
(*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1);
2928
if ((countLho<=1)&&(countRho<=1)&&(countPart<=1)) {
2936
if (posPoint->secondBest[suit].hand==hand) {
2937
posPoint->winRanks[depth][suit]|=
2938
bitMapRank[posPoint->secondBest[suit].rank];
2942
if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) {
2943
/*if (trump==suit) {*/
2944
(*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1);
2945
(*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1);
2947
if ((countLho<=2)&&(countRho<=2)&&(countPart<=2)) {
2956
for (k=0; k<=3; k++)
2957
aggr|=posPoint->rankInSuit[k][suit];
2958
if (rel[aggr].absRank[3][suit].hand==hand) {
2960
posPoint->winRanks[depth][suit]|=
2961
bitMapRank[rel[aggr].absRank[3][suit].rank];
2964
if ((countLho<=3)&&(countRho<=3)&&(countPart<=3)) {
2974
else if ((posPoint->secondBest[suit].hand==partner[hand])
2975
&&(countOwn>1)&&(countPart>1)) {
2976
/* Second best at partner and suit length of own
2977
hand and partner > 1 */
2978
posPoint->winRanks[depth][suit]|=
2979
bitMapRank[posPoint->secondBest[suit].rank];
2983
if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) {
2984
/*if (trump==suit) {*/
2985
(*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1);
2986
(*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1);
2988
if ((countLho<=2)&&(countRho<=2)&&((countPart<=2)||(countOwn<=2))) {
2989
qt+=Max(countOwn-2,countPart-2);
2995
/*else if (countPart>2) {
2997
for (k=0; k<=3; k++)
2998
aggr|=posPoint->rankInSuit[k][suit];
2999
if (rel[aggr].absRank[3][suit].hand==hand) {
3001
posPoint->winRanks[depth][suit]|=
3002
bitMapRank[rel[aggr].absRank[3][suit].rank];
3016
int QuickTricksPartnerHandTrump(int hand, struct pos *posPoint, int cutoff, int depth,
3017
int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn,
3018
int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId) {
3019
/* res=0 Continue with same suit.
3021
res=2 Continue with next suit. */
3024
unsigned short ranks;
3028
if (((countLho!=0) || (lhoTrumpRanks==0)) && ((countRho!=0) || (rhoTrumpRanks==0))) {
3029
posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank];
3030
posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
3031
qt++; /* A trick can be taken */
3034
if ((countLho<=1)&&(countRho<=1)&&(countOwn<=1)&&(lhoTrumpRanks==0)&&
3035
(rhoTrumpRanks==0)) {
3044
if (posPoint->secondBest[suit].hand==partner[hand]) {
3045
/* Second best found in partners hand */
3046
if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
3047
/* Opponents have no trump */
3048
posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank];
3049
posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
3053
if ((countLho<=2)&&(countRho<=2)&&(countOwn<=2)) {
3062
else if ((posPoint->secondBest[suit].hand==hand)&&(countPart>1)&&(countOwn>1)) {
3063
/* Second best found in own hand and suit lengths of own hand and partner > 1*/
3064
if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
3065
/* Opponents have no trump */
3066
posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank];
3067
posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
3071
if ((countLho<=2)&&(countRho<=2)&&((countOwn<=2)||(countPart<=2))) {
3072
qt+=Max(countPart-2,countOwn-2);
3080
else if ((suit==commSuit)&&(posPoint->secondBest[suit].hand==lho[hand])&&
3081
((countLho>=2)||(lhoTrumpRanks==0))&&((countRho>=2)||(rhoTrumpRanks==0))) {
3083
for (k=0; k<=3; k++)
3084
ranks|=posPoint->rankInSuit[k][suit];
3085
if (localVar[thrId].rel[ranks].absRank[3][suit].hand==partner[hand]) {
3086
posPoint->winRanks[depth][suit]|=bitMapRank[localVar[thrId].rel[ranks].absRank[3][suit].rank];
3087
posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
3091
if ((countOwn<=2)&&(countLho<=2)&&(countRho<=2)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) {
3103
int QuickTricksPartnerHandNT(int hand, struct pos *posPoint, int cutoff, int depth,
3104
int countLho, int countRho, int countOwn,
3105
int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId) {
3107
int qt, k/*, found, rr*/;
3108
unsigned short ranks;
3113
posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank];
3114
posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank];
3118
if ((countLho<=1)&&(countRho<=1)&&(countOwn<=1)) {
3126
if ((posPoint->secondBest[suit].hand==partner[hand])&&(1/*countPart>0*/)) {
3127
/* Second best found in partners hand */
3128
posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank];
3132
if ((countLho<=2)&&(countRho<=2)&&(countOwn<=2)) {
3140
else if ((posPoint->secondBest[suit].hand==hand)
3141
&&(countPart>1)&&(countOwn>1)) {
3142
/* Second best found in own hand and own and
3143
partner's suit length > 1 */
3144
posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank];
3148
if ((countLho<=2)&&(countRho<=2)&&((countOwn<=2)||(countPart<=2))) {
3149
qt+=Max(countPart-2,countOwn-2);
3156
else if ((suit==commSuit)&&(posPoint->secondBest[suit].hand==lho[hand])) {
3158
for (k=0; k<=3; k++)
3159
ranks=ranks | posPoint->rankInSuit[k][suit];
3160
if (localVar[thrId].rel[ranks].absRank[3][suit].hand==partner[hand]) {
3161
posPoint->winRanks[depth][suit]|=bitMapRank[localVar[thrId].rel[ranks].absRank[3][suit].rank];
3165
if ((countOwn<=2)&&(countLho<=2)&&(countRho<=2)) {
3166
qtricks+=countPart-2;
3177
int LaterTricksMIN(struct pos *posPoint, int hand, int depth, int target,
3178
int trump, int thrId) {
3179
int hh, ss, k, h, sum=0;
3180
unsigned short aggr;
3182
if ((trump==4)||(posPoint->winner[trump].rank==0)) {
3183
for (ss=0; ss<=3; ss++) {
3184
hh=posPoint->winner[ss].hand;
3186
if (localVar[thrId].nodeTypeStore[hh]==MAXNODE)
3187
sum+=Max(posPoint->length[hh][ss], posPoint->length[partner[hh]][ss]);
3190
if ((posPoint->tricksMAX+sum<target)&&
3191
(sum>0)&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3192
if ((posPoint->tricksMAX+(depth>>2)<target)) {
3193
for (ss=0; ss<=3; ss++) {
3194
if (posPoint->winner[ss].hand==-1)
3195
posPoint->winRanks[depth][ss]=0;
3196
else if (localVar[thrId].nodeTypeStore[posPoint->winner[ss].hand]==MINNODE) {
3197
if ((posPoint->rankInSuit[partner[posPoint->winner[ss].hand]][ss]==0)&&
3198
(posPoint->rankInSuit[lho[posPoint->winner[ss].hand]][ss]==0)&&
3199
(posPoint->rankInSuit[rho[posPoint->winner[ss].hand]][ss]==0))
3200
posPoint->winRanks[depth][ss]=0;
3202
posPoint->winRanks[depth][ss]=bitMapRank[posPoint->winner[ss].rank];
3205
posPoint->winRanks[depth][ss]=0;
3211
else if ((trump!=4) && (posPoint->winner[trump].rank!=0) &&
3212
(localVar[thrId].nodeTypeStore[posPoint->winner[trump].hand]==MINNODE)) {
3213
if ((posPoint->length[hand][trump]==0)&&
3214
(posPoint->length[partner[hand]][trump]==0)) {
3215
if (((posPoint->tricksMAX+(depth>>2)+1-
3216
Max(posPoint->length[lho[hand]][trump],
3217
posPoint->length[rho[hand]][trump]))<target)
3218
&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3219
for (ss=0; ss<=3; ss++)
3220
posPoint->winRanks[depth][ss]=0;
3224
else if (((posPoint->tricksMAX+(depth>>2))<target)&&
3225
(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3226
for (ss=0; ss<=3; ss++)
3227
posPoint->winRanks[depth][ss]=0;
3228
posPoint->winRanks[depth][trump]=
3229
bitMapRank[posPoint->winner[trump].rank];
3233
hh=posPoint->secondBest[trump].hand;
3235
if ((localVar[thrId].nodeTypeStore[hh]==MINNODE)&&(posPoint->secondBest[trump].rank!=0)) {
3236
if (((posPoint->length[hh][trump]>1) ||
3237
(posPoint->length[partner[hh]][trump]>1))&&
3238
((posPoint->tricksMAX+(depth>>2)-1)<target)&&(depth>0)
3239
&&(depth!=localVar[thrId].iniDepth)) {
3240
for (ss=0; ss<=3; ss++)
3241
posPoint->winRanks[depth][ss]=0;
3242
posPoint->winRanks[depth][trump]=
3243
bitMapRank[posPoint->secondBest[trump].rank] ;
3250
else if (trump!=4) {
3251
hh=posPoint->secondBest[trump].hand;
3253
if ((localVar[thrId].nodeTypeStore[hh]==MINNODE)&&
3254
(posPoint->length[hh][trump]>1)) {
3255
if (posPoint->winner[trump].hand==rho[hh]) {
3256
if (((posPoint->tricksMAX+(depth>>2))<target)&&
3257
(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3258
for (ss=0; ss<=3; ss++)
3259
posPoint->winRanks[depth][ss]=0;
3260
posPoint->winRanks[depth][trump]=
3261
bitMapRank[posPoint->secondBest[trump].rank];
3267
for (k=0; k<=3; k++)
3268
aggr|=posPoint->rankInSuit[k][trump];
3269
h=localVar[thrId].rel[aggr].absRank[3][trump].hand;
3271
if ((localVar[thrId].nodeTypeStore[h]==MINNODE)&&
3272
((posPoint->tricksMAX+(depth>>2))<target)&&
3273
(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3274
for (ss=0; ss<=3; ss++)
3275
posPoint->winRanks[depth][ss]=0;
3276
posPoint->winRanks[depth][trump]=
3277
bitMapRank[localVar[thrId].rel[aggr].absRank[3][trump].rank];
3289
int LaterTricksMAX(struct pos *posPoint, int hand, int depth, int target,
3290
int trump, int thrId) {
3291
int hh, ss, k, h, sum=0;
3292
unsigned short aggr;
3294
if ((trump==4)||(posPoint->winner[trump].rank==0)) {
3295
for (ss=0; ss<=3; ss++) {
3296
hh=posPoint->winner[ss].hand;
3298
if (localVar[thrId].nodeTypeStore[hh]==MINNODE)
3299
sum+=Max(posPoint->length[hh][ss], posPoint->length[partner[hh]][ss]);
3302
if ((posPoint->tricksMAX+(depth>>2)+1-sum>=target)&&
3303
(sum>0)&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3304
if ((posPoint->tricksMAX+1>=target)) {
3305
for (ss=0; ss<=3; ss++) {
3306
if (posPoint->winner[ss].hand==-1)
3307
posPoint->winRanks[depth][ss]=0;
3308
else if (localVar[thrId].nodeTypeStore[posPoint->winner[ss].hand]==MAXNODE) {
3309
if ((posPoint->rankInSuit[partner[posPoint->winner[ss].hand]][ss]==0)&&
3310
(posPoint->rankInSuit[lho[posPoint->winner[ss].hand]][ss]==0)&&
3311
(posPoint->rankInSuit[rho[posPoint->winner[ss].hand]][ss]==0))
3312
posPoint->winRanks[depth][ss]=0;
3314
posPoint->winRanks[depth][ss]=bitMapRank[posPoint->winner[ss].rank];
3317
posPoint->winRanks[depth][ss]=0;
3323
else if ((trump!=4) && (posPoint->winner[trump].rank!=0) &&
3324
(localVar[thrId].nodeTypeStore[posPoint->winner[trump].hand]==MAXNODE)) {
3325
if ((posPoint->length[hand][trump]==0)&&
3326
(posPoint->length[partner[hand]][trump]==0)) {
3327
if (((posPoint->tricksMAX+Max(posPoint->length[lho[hand]][trump],
3328
posPoint->length[rho[hand]][trump]))>=target)
3329
&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3330
for (ss=0; ss<=3; ss++)
3331
posPoint->winRanks[depth][ss]=0;
3335
else if (((posPoint->tricksMAX+1)>=target)
3336
&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) {
3337
for (ss=0; ss<=3; ss++)
3338
posPoint->winRanks[depth][ss]=0;
3339
posPoint->winRanks[depth][trump]=
3340
bitMapRank[posPoint->winner[trump].rank];
3344
hh=posPoint->secondBest[trump].hand;
3346
if ((localVar[thrId].nodeTypeStore[hh]==MAXNODE)&&(posPoint->secondBest[trump].rank!=0)) {
3347
if (((posPoint->length[hh][trump]>1) ||
3348
(posPoint->length[partner[hh]][trump]>1))&&
3349
((posPoint->tricksMAX+2)>=target)&&(depth>0)
3350
&&(depth!=localVar[thrId].iniDepth)) {
3351
for (ss=0; ss<=3; ss++)
3352
posPoint->winRanks[depth][ss]=0;
3353
posPoint->winRanks[depth][trump]=
3354
bitMapRank[posPoint->secondBest[trump].rank];
3362
else if (trump!=4) {
3363
hh=posPoint->secondBest[trump].hand;
3365
if ((localVar[thrId].nodeTypeStore[hh]==MAXNODE)&&
3366
(posPoint->length[hh][trump]>1)) {
3367
if (posPoint->winner[trump].hand==rho[hh]) {
3368
if (((posPoint->tricksMAX+1)>=target)&&(depth>0)
3369
&&(depth!=localVar[thrId].iniDepth)) {
3370
for (ss=0; ss<=3; ss++)
3371
posPoint->winRanks[depth][ss]=0;
3372
posPoint->winRanks[depth][trump]=
3373
bitMapRank[posPoint->secondBest[trump].rank] ;
3379
for (k=0; k<=3; k++)
3380
aggr|=posPoint->rankInSuit[k][trump];
3381
h=localVar[thrId].rel[aggr].absRank[3][trump].hand;
3383
if ((localVar[thrId].nodeTypeStore[h]==MAXNODE)&&
3384
((posPoint->tricksMAX+1)>=target)&&(depth>0)
3385
&&(depth!=localVar[thrId].iniDepth)) {
3386
for (ss=0; ss<=3; ss++)
3387
posPoint->winRanks[depth][ss]=0;
3388
posPoint->winRanks[depth][trump]=
3389
bitMapRank[localVar[thrId].rel[aggr].absRank[3][trump].rank];
3401
int MoveGen(struct pos * posPoint, int depth, int trump, struct movePlyType *mply, int thrId) {
3402
int suit, k, m, r, s, t, q, first, state;
3405
int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth,
3406
unsigned short notVoidInSuit, int trump, int thrId);
3407
int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth,
3408
unsigned short notVoidInSuit, int thrId);
3411
localVar[thrId].lowestWin[depth][k]=0;
3414
r=posPoint->handRelFirst;
3415
assert((r>=0)&&(r<=3));
3416
first=posPoint->first[depth];
3420
s=localVar[thrId].movePly[depth+r].current; /* Current move of first hand */
3421
t=localVar[thrId].movePly[depth+r].move[s].suit; /* Suit played by first hand */
3422
ris=posPoint->rankInSuit[q][t];
3425
/* Not first hand and not void in suit */
3426
k=14; state=MOVESVALID;
3428
if ((ris & bitMapRank[k])&&(state==MOVESVALID)) {
3429
/* Only first move in sequence is generated */
3430
mply->move[m].suit=t;
3431
mply->move[m].rank=k;
3432
mply->move[m].sequence=0;
3436
else if (state==MOVESLOCKED)
3437
if ((posPoint->removedRanks[t] & bitMapRank[k])==0) {
3438
if ((ris & bitMapRank[k])==0)
3439
/* If the card still exists and it is not in own hand */
3442
/* If the card still exists and it is in own hand */
3443
mply->move[m-1].sequence|=bitMapRank[k];
3448
if ((trump!=4)&&(posPoint->winner[trump].rank!=0)) {
3449
for (k=0; k<=m-1; k++)
3450
mply->move[k].weight=WeightAllocTrump(posPoint,
3451
&(mply->move[k]), depth, ris, trump, thrId);
3454
for (k=0; k<=m-1; k++)
3455
mply->move[k].weight=WeightAllocNT(posPoint,
3456
&(mply->move[k]), depth, ris, thrId);
3462
MergeSort(m, mply->move);
3463
if (depth!=localVar[thrId].iniDepth)
3466
m=AdjustMoveList(thrId);
3472
/* First hand or void in suit */
3473
for (suit=0; suit<=3; suit++) {
3474
k=14; state=MOVESVALID;
3476
if ((posPoint->rankInSuit[q][suit] & bitMapRank[k])&&
3477
(state==MOVESVALID)) {
3478
/* Only first move in sequence is generated */
3479
mply->move[m].suit=suit;
3480
mply->move[m].rank=k;
3481
mply->move[m].sequence=0;
3485
else if (state==MOVESLOCKED)
3486
if ((posPoint->removedRanks[suit] & bitMapRank[k])==0) {
3487
if ((posPoint->rankInSuit[q][suit] & bitMapRank[k])==0)
3488
/* If the card still exists and it is not in own hand */
3491
/* If the card still exists and it is in own hand */
3492
mply->move[m-1].sequence|=bitMapRank[k];
3498
if ((trump!=4)&&(posPoint->winner[trump].rank!=0)) {
3499
for (k=0; k<=m-1; k++)
3500
mply->move[k].weight=WeightAllocTrump(posPoint,
3501
&(mply->move[k]), depth, 0/*ris*/, trump, thrId);
3504
for (k=0; k<=m-1; k++)
3505
mply->move[k].weight=WeightAllocNT(posPoint,
3506
&(mply->move[k]), depth, 0/*ris*/, thrId);
3511
MergeSort(m, mply->move);
3513
if (depth!=localVar[thrId].iniDepth)
3516
m=AdjustMoveList(thrId);
3522
int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth,
3523
unsigned short notVoidInSuit, int thrId) {
3524
int weight=0, k, l, kk, ll, suit, suitAdd=0, leadSuit;
3525
int suitWeightDelta, first, q;
3526
int rRank, thirdBestHand;
3527
int winMove=FALSE; /* If winMove is true, current move can win the current trick. */
3528
unsigned short suitCount, suitCountLH, suitCountRH, aggr;
3529
int countLH, countRH;
3531
first=posPoint->first[depth];
3532
q=handId(first, posPoint->handRelFirst);
3535
for (k=0; k<=3; k++)
3536
aggr|=posPoint->rankInSuit[k][suit];
3537
rRank=localVar[thrId].rel[aggr].relRank[mp->rank][suit];
3539
switch (posPoint->handRelFirst) {
3541
thirdBestHand=localVar[thrId].rel[aggr].absRank[3][suit].hand;
3542
suitCount=posPoint->length[q][suit];
3543
suitCountLH=posPoint->length[lho[q]][suit];
3544
suitCountRH=posPoint->length[rho[q]][suit];
3546
if (suitCountLH!=0) {
3547
countLH=(suitCountLH<<2);
3552
if (suitCountRH!=0) {
3553
countRH=(suitCountRH<<2);
3558
/* Discourage a suit selection where the search tree appears larger than for the
3559
altenative suits: the search is estimated to be small when the added number of
3560
alternative cards to play for the opponents is small. */
3562
suitWeightDelta=-((countLH+countRH)<<5)/19;
3564
if (posPoint->winner[suit].rank==mp->rank)
3566
else if (posPoint->rankInSuit[partner[first]][suit] >
3567
(posPoint->rankInSuit[lho[first]][suit] |
3568
posPoint->rankInSuit[rho[first]][suit])) {
3573
/* Discourage suit if RHO has second best card.
3574
Exception: RHO has singleton. */
3575
if (posPoint->secondBest[suit].hand==rho[q]) {
3579
/* Encourage playing suit if LHO has second highest rank. */
3580
else if (posPoint->secondBest[suit].hand==lho[q])
3581
suitWeightDelta+=14;
3583
/* Higher weight if also second best rank is present on current side to play, or
3584
if second best is a singleton at LHO or RHO. */
3586
if (((posPoint->secondBest[suit].hand!=lho[first])
3587
||(suitCountLH==1))&&
3588
((posPoint->secondBest[suit].hand!=rho[first])
3589
||(suitCountRH==1)))
3590
weight=suitWeightDelta+41/*48*/+rRank;
3592
/* Encourage playing second highest rank if hand also has
3593
third highest rank. */
3595
else if ((mp->sequence)&&
3596
(mp->rank==posPoint->secondBest[suit].rank))
3597
weight=suitWeightDelta+39;
3599
weight=suitWeightDelta+20+rRank;
3601
/* Encourage playing cards that previously caused search cutoff
3602
or was stored as the best move in a transposition table entry match. */
3604
if ((localVar[thrId].bestMove[depth].suit==suit)&&
3605
(localVar[thrId].bestMove[depth].rank==mp->rank))
3606
weight+=123/*122*//*112*//*73*/;
3607
else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&&
3608
(localVar[thrId].bestMoveTT[depth].rank==mp->rank))
3609
weight+=24/*20*//*17*//*14*/;
3612
/* Discourage suit if RHO has winning or second best card.
3613
Exception: RHO has singleton. */
3615
if ((posPoint->winner[suit].hand==rho[q])||
3616
(posPoint->secondBest[suit].hand==rho[q])) {
3622
/* Try suit if LHO has winning card and partner second best.
3623
Exception: partner has singleton. */
3625
else if ((posPoint->winner[suit].hand==lho[q])&&
3626
(posPoint->secondBest[suit].hand==partner[q])) {
3628
/* This case was suggested by Jo�l Bradmetz. */
3630
if (posPoint->length[partner[q]][suit]!=1)
3631
suitWeightDelta+=31/*34*//*37*//*32*//*20*/;
3634
/* Encourage playing the suit if the hand together with partner have both the 2nd highest
3635
and the 3rd highest cards such that the side of the hand has the highest card in the
3636
next round playing this suit. */
3638
if ((posPoint->secondBest[suit].hand==partner[first])&&(partner[first]==thirdBestHand))
3639
suitWeightDelta+=22/*10*/;
3640
else if(((posPoint->secondBest[suit].hand==first)&&(partner[first]==thirdBestHand)&&
3641
(posPoint->length[partner[first]][suit]>1))||((posPoint->secondBest[suit].hand==partner[first])&&
3642
(first==thirdBestHand)&&(posPoint->length[partner[first]][suit]>1)))
3643
suitWeightDelta+=24/*10*/;
3645
/* Higher weight if LHO or RHO has the highest (winning) card as a singleton. */
3647
if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first]))
3648
||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first])))
3649
weight=suitWeightDelta+25/*23*//*22*/+rRank;
3650
else if (posPoint->winner[suit].hand==first) {
3651
weight=suitWeightDelta-20/*24*//*27*//*12*//*10*/+rRank;
3654
/* Encourage playing second highest rank if hand also has
3655
third highest rank. */
3657
else if ((mp->sequence)&&
3658
(mp->rank==posPoint->secondBest[suit].rank))
3659
weight=suitWeightDelta+44/*42*/;
3660
else if (mp->sequence)
3661
weight=suitWeightDelta+31/*32*/-rRank;
3663
weight=suitWeightDelta+12+rRank;
3665
/* Encourage playing cards that previously caused search cutoff
3666
or was stored as the best move in a transposition table entry match. */
3668
if ((localVar[thrId].bestMove[depth].suit==suit)&&
3669
(localVar[thrId].bestMove[depth].rank==mp->rank))
3670
weight+=47/*45*//*39*//*38*/;
3671
else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&&
3672
(localVar[thrId].bestMoveTT[depth].rank==mp->rank))
3673
weight+=13/*15*//*16*//*19*//*14*/;
3679
leadSuit=posPoint->move[depth+1].suit;
3680
if (leadSuit==suit) {
3681
if (bitMapRank[mp->rank]>
3682
(bitMapRank[posPoint->move[depth+1].rank] |
3683
posPoint->rankInSuit[partner[first]][suit]))
3685
else if (posPoint->rankInSuit[rho[first]][suit]>
3686
(bitMapRank[posPoint->move[depth+1].rank] |
3687
posPoint->rankInSuit[partner[first]][suit]))
3691
/* Side with highest rank in leadSuit wins */
3693
if (posPoint->rankInSuit[rho[first]][leadSuit] >
3694
(posPoint->rankInSuit[partner[first]][leadSuit] |
3695
bitMapRank[posPoint->move[depth+1].rank]))
3700
if (!notVoidInSuit) {
3701
suitCount=posPoint->length[q][suit];
3702
suitAdd=(suitCount<<6)/(23/*20*//*21*//*24*//*30*//*35*/);
3703
if (posPoint->secondBest[suit].hand==q) {
3704
/* Discourage suit discard if 2nd highest card becomes singleton. */
3709
/* Discourage suit discard of highest card. */
3711
else if ((suitCount==1)&&(posPoint->winner[suit].hand==q))
3714
/*Encourage discard of low cards in long suits. */
3715
weight=/*60*/-(mp->rank)+suitAdd;
3722
if (!notVoidInSuit) {
3723
suitCount=posPoint->length[q][suit];
3724
suitAdd=(suitCount<<6)/33;
3726
/* Discourage suit discard if 2nd highest card becomes singleton. */
3727
if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
3730
/* Discourage suit discard of highest card. */
3731
else if ((suitCount==1)&&(posPoint->winner[suit].hand==q))
3734
/*Encourage discard of low cards in long suits. */
3735
weight=-(mp->rank)+suitAdd;
3739
/* If lowest rank for either partner to leading hand
3740
or rho is higher than played card for lho,
3741
lho should play as low card as possible */
3743
kk=posPoint->rankInSuit[partner[first]][leadSuit];
3744
ll=posPoint->rankInSuit[rho[first]][leadSuit];
3745
k=kk & (-kk); l=ll & (-ll); /* Only least significant 1 bit of
3746
bit map ranks for partner and RHO. */
3748
if ((k > bitMapRank[mp->rank])||(l > bitMapRank[mp->rank]))
3750
else if (mp->rank > posPoint->move[depth+1].rank) {
3752
weight=/*0*/10+rRank;
3755
weight=13-(mp->rank);
3756
/*weight=-5+rRank;*/
3769
leadSuit=posPoint->move[depth+2].suit;
3770
if (WinningMoveNT(mp, &(posPoint->move[depth+1]),thrId)) {
3771
if (bitMapRank[mp->rank] >
3772
posPoint->rankInSuit[rho[first]][suit])
3775
else if (posPoint->high[depth+1]==first) {
3776
if (posPoint->rankInSuit[rho[first]][leadSuit]
3777
< bitMapRank[posPoint->move[depth+2].rank])
3783
if (!notVoidInSuit) {
3784
suitCount=posPoint->length[q][suit];
3785
suitAdd=(suitCount<<6)/(17/*27*//*30*//*35*/);
3787
/* Discourage suit discard if 2nd highest card becomes singleton. */
3788
if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
3789
suitAdd-=(6/*2*//*5*/);
3790
weight=-(mp->rank)+suitAdd;
3797
if (!notVoidInSuit) {
3798
suitCount=posPoint->length[q][suit];
3799
suitAdd=(suitCount<<6)/(24/*26*//*29*//*35*/);
3800
if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
3802
/* Discourage suit discard of highest card. */
3803
else if ((suitCount==1)&&(posPoint->winner[suit].hand==q))
3806
weight=-(mp->rank)+suitAdd;
3811
k=posPoint->rankInSuit[rho[first]][suit];
3812
if ((k & (-k)) > bitMapRank[mp->rank])
3814
else if (WinningMoveNT(mp, &(posPoint->move[depth+1]), thrId)) {
3815
if ((mp->rank==posPoint->secondBest[leadSuit].rank)&&
3818
else if (mp->sequence)
3819
weight=20-(mp->rank);
3821
weight=10-(mp->rank);
3824
weight=-10-(mp->rank);
3831
if (!notVoidInSuit) {
3832
suitCount=posPoint->length[q][suit];
3833
suitAdd=(suitCount<<6)/(27/*35*/);
3834
if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
3836
else if ((suitCount==1)&&(posPoint->winner[suit].hand==q))
3837
suitAdd-=(8/*9*//*8*//*5*/);
3839
weight=30-(mp->rank)+suitAdd;
3841
else if ((posPoint->high[depth+1])==(lho[first])) {
3842
/* If the current winning move is given by the partner */
3843
weight=30-(mp->rank);
3845
else if (WinningMoveNT(mp, &(posPoint->move[depth+1]),thrId))
3846
/* If present move is superior to current winning move and the
3847
current winning move is not given by the partner */
3848
weight=30-(mp->rank);
3850
/* If present move is not superior to current winning move and the
3851
current winning move is not given by the partner */
3852
weight=14-(mp->rank);
3859
int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth,
3860
unsigned short notVoidInSuit, int trump, int thrId) {
3861
int weight=0, k, l, kk, ll, suit, suitAdd=0, leadSuit;
3862
int suitWeightDelta, first, q, rRank, thirdBestHand;
3864
int winMove=FALSE; /* If winMove is true, current move can win the current trick. */
3865
unsigned short suitCount, suitCountLH, suitCountRH, aggr;
3866
int countLH, countRH;
3868
first=posPoint->first[depth];
3869
q=handId(first, posPoint->handRelFirst);
3872
for (k=0; k<=3; k++)
3873
aggr|=posPoint->rankInSuit[k][suit];
3874
rRank=localVar[thrId].rel[aggr].relRank[mp->rank][suit];
3876
switch (posPoint->handRelFirst) {
3878
thirdBestHand=localVar[thrId].rel[aggr].absRank[3][suit].hand;
3879
suitCount=posPoint->length[q][suit];
3880
suitCountLH=posPoint->length[lho[q]][suit];
3881
suitCountRH=posPoint->length[rho[q]][suit];
3883
/* Discourage suit if LHO or RHO can ruff. */
3885
if ((suit!=trump) &&
3886
(((posPoint->rankInSuit[lho[q]][suit]==0) &&
3887
(posPoint->rankInSuit[lho[q]][trump]!=0)) ||
3888
((posPoint->rankInSuit[rho[q]][suit]==0) &&
3889
(posPoint->rankInSuit[rho[q]][trump]!=0))))
3890
suitBonus=-17/*20*//*-10*/;
3892
/* Encourage suit if partner can ruff. */
3894
if ((suit!=trump)&&(posPoint->length[partner[q]][suit]==0)&&
3895
(posPoint->length[partner[q]][trump]>0)&&(suitCountRH>0))
3896
suitBonus+=26/*28*/;
3898
/* Discourage suit if RHO has high card. */
3900
if ((posPoint->winner[suit].hand==rho[q])||
3901
(posPoint->secondBest[suit].hand==rho[q])) {
3903
suitBonus-=11/*12*//*13*//*18*/;
3906
/* Try suit if LHO has winning card and partner second best.
3907
Exception: partner has singleton. */
3909
else if ((posPoint->winner[suit].hand==lho[q])&&
3910
(posPoint->secondBest[suit].hand==partner[q])) {
3912
/* This case was suggested by Jo�l Bradmetz. */
3914
if (posPoint->length[partner[q]][suit]!=1)
3915
suitBonus+=30/*28*//*22*/;
3918
/* Encourage play of suit where partner wins and
3919
returns the suit for a ruff. */
3920
if ((suit!=trump)&&(suitCount==1)&&
3921
(posPoint->length[q][trump]>0)&&
3922
(posPoint->length[partner[q]][suit]>1)&&
3923
(posPoint->winner[suit].hand==partner[q]))
3924
suitBonus+=23/*24*//*19*//*16*/;
3927
countLH=(suitCountLH<<2);
3931
countRH=(suitCountRH<<2);
3935
/* Discourage a suit selection where the search tree appears larger than for the
3936
altenative suits: the search is estimated to be small when the added number of
3937
alternative cards to play for the opponents is small. */
3939
suitWeightDelta=suitBonus-
3940
((countLH+countRH)<<5)/(12/*15*/);
3942
if (posPoint->winner[suit].rank==mp->rank) {
3943
if ((suit!=trump)) {
3944
if ((posPoint->length[partner[first]][suit]!=0)||
3945
(posPoint->length[partner[first]][trump]==0)) {
3946
if (((posPoint->length[lho[first]][suit]!=0)||
3947
(posPoint->length[lho[first]][trump]==0))&&
3948
((posPoint->length[rho[first]][suit]!=0)||
3949
(posPoint->length[rho[first]][trump]==0)))
3952
else if (((posPoint->length[lho[first]][suit]!=0)||
3953
(posPoint->rankInSuit[partner[first]][trump]>
3954
posPoint->rankInSuit[lho[first]][trump]))&&
3955
((posPoint->length[rho[first]][suit]!=0)||
3956
(posPoint->rankInSuit[partner[first]][trump]>
3957
posPoint->rankInSuit[rho[first]][trump])))
3963
else if (posPoint->rankInSuit[partner[first]][suit] >
3964
(posPoint->rankInSuit[lho[first]][suit] |
3965
posPoint->rankInSuit[rho[first]][suit])) {
3967
if (((posPoint->length[lho[first]][suit]!=0)||
3968
(posPoint->length[lho[first]][trump]==0))&&
3969
((posPoint->length[rho[first]][suit]!=0)||
3970
(posPoint->length[rho[first]][trump]==0)))
3976
else if (suit!=trump) {
3977
if ((posPoint->length[partner[first]][suit]==0)&&
3978
(posPoint->length[partner[first]][trump]!=0)) {
3979
if ((posPoint->length[lho[first]][suit]==0)&&
3980
(posPoint->length[lho[first]][trump]!=0)&&
3981
(posPoint->length[rho[first]][suit]==0)&&
3982
(posPoint->length[rho[first]][trump]!=0)) {
3983
if (posPoint->rankInSuit[partner[first]][trump]>
3984
(posPoint->rankInSuit[lho[first]][trump] |
3985
posPoint->rankInSuit[rho[first]][trump]))
3988
else if ((posPoint->length[lho[first]][suit]==0)&&
3989
(posPoint->length[lho[first]][trump]!=0)) {
3990
if (posPoint->rankInSuit[partner[first]][trump]
3991
> posPoint->rankInSuit[lho[first]][trump])
3994
else if ((posPoint->length[rho[first]][suit]==0)&&
3995
(posPoint->length[rho[first]][trump]!=0)) {
3996
if (posPoint->rankInSuit[partner[first]][trump]
3997
> posPoint->rankInSuit[rho[first]][trump])
4007
/* Encourage ruffing LHO or RHO singleton, highest card. */
4009
if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first]))
4010
||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first])))
4011
weight=suitWeightDelta+39+rRank;
4013
/* Lead hand has the highest card. */
4015
else if (posPoint->winner[suit].hand==first) {
4017
/* Also, partner has second highest card. */
4019
if (posPoint->secondBest[suit].hand==partner[first])
4020
weight=suitWeightDelta+46+rRank;
4021
else if (posPoint->winner[suit].rank==mp->rank)
4023
/* If the current card to play is the highest card. */
4025
weight=suitWeightDelta+31;
4027
weight=suitWeightDelta-2+rRank;
4029
else if (posPoint->winner[suit].hand==partner[first]) {
4030
/* If partner has highest card */
4031
if (posPoint->secondBest[suit].hand==first)
4032
weight=suitWeightDelta+35/*35*//*46*//*50*/+rRank;
4034
weight=suitWeightDelta+24/*35*/+rRank;
4036
/* Encourage playing second highest rank if hand also has
4037
third highest rank. */
4039
else if ((mp->sequence)&&
4040
(mp->rank==posPoint->secondBest[suit].rank))
4041
weight=suitWeightDelta+41;
4042
else if (mp->sequence)
4043
weight=suitWeightDelta+17+rRank;
4045
weight=suitWeightDelta+11+rRank;
4047
/* Encourage playing cards that previously caused search cutoff
4048
or was stored as the best move in a transposition table entry match. */
4050
if ((localVar[thrId].bestMove[depth].suit==suit)&&
4051
(localVar[thrId].bestMove[depth].rank==mp->rank))
4052
weight+=53/*50*//*52*/;
4053
else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&&
4054
(localVar[thrId].bestMoveTT[depth].rank==mp->rank))
4055
weight+=14/*15*//*12*//*11*/;
4059
/* Encourage playing the suit if the hand together with partner have both the 2nd highest
4060
and the 3rd highest cards such that the side of the hand has the highest card in the
4061
next round playing this suit. */
4063
if ((posPoint->secondBest[suit].hand==partner[first])&&(partner[first]==thirdBestHand))
4064
suitWeightDelta+=20/*22*/;
4065
else if(((posPoint->secondBest[suit].hand==first)&&(partner[first]==thirdBestHand)&&
4066
(posPoint->length[partner[first]][suit]>1))||
4067
((posPoint->secondBest[suit].hand==partner[first])&&
4068
(first==thirdBestHand)&&(posPoint->length[partner[first]][suit]>1)))
4069
suitWeightDelta+=20/*24*/;
4071
/* Higher weight if LHO or RHO has the highest (winning) card as a singleton. */
4073
if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first]))
4074
||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first])))
4075
weight=suitWeightDelta+rRank-2;
4076
else if (posPoint->winner[suit].hand==first) {
4077
if (posPoint->secondBest[suit].hand==partner[first])
4079
/* Opponents win by ruffing */
4081
weight=suitWeightDelta+33+rRank;
4082
else if (posPoint->winner[suit].rank==mp->rank)
4084
/* Opponents win by ruffing */
4086
weight=suitWeightDelta+36;
4088
weight=suitWeightDelta-17+rRank;
4090
else if (posPoint->winner[suit].hand==partner[first]) {
4092
/* Opponents win by ruffing */
4094
weight=suitWeightDelta+33+rRank;
4096
/* Encourage playing second highest rank if hand also has
4097
third highest rank. */
4099
else if ((mp->sequence)&&
4100
(mp->rank==posPoint->secondBest[suit].rank))
4101
weight=suitWeightDelta+31;
4103
weight=suitWeightDelta+13-(mp->rank);
4105
/* Encourage playing cards that previously caused search cutoff
4106
or was stored as the best move in a transposition table entry match. */
4108
if ((localVar[thrId].bestMove[depth].suit==suit)&&
4109
(localVar[thrId].bestMove[depth].rank==mp->rank))
4111
else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&&
4112
(localVar[thrId].bestMoveTT[depth].rank==mp->rank))
4113
weight+=(3/*4*//*10*//*9*/);
4119
leadSuit=posPoint->move[depth+1].suit;
4120
if (leadSuit==suit) {
4121
if (bitMapRank[mp->rank]>
4122
(bitMapRank[posPoint->move[depth+1].rank] |
4123
posPoint->rankInSuit[partner[first]][suit])) {
4125
if ((posPoint->length[partner[first]][suit]!=0)||
4126
(posPoint->length[partner[first]][trump]==0))
4128
else if ((posPoint->length[rho[first]][suit]==0)
4129
&&(posPoint->length[rho[first]][trump]!=0)
4130
&&(posPoint->rankInSuit[rho[first]][trump]>
4131
posPoint->rankInSuit[partner[first]][trump]))
4137
else if (posPoint->rankInSuit[rho[first]][suit]>
4138
(bitMapRank[posPoint->move[depth+1].rank] |
4139
posPoint->rankInSuit[partner[first]][suit])) {
4141
if ((posPoint->length[partner[first]][suit]!=0)||
4142
(posPoint->length[partner[first]][trump]==0))
4148
else if (bitMapRank[posPoint->move[depth+1].rank] >
4149
(posPoint->rankInSuit[rho[first]][suit] |
4150
posPoint->rankInSuit[partner[first]][suit] |
4151
bitMapRank[mp->rank])) {
4153
if ((posPoint->length[rho[first]][suit]==0)&&
4154
(posPoint->length[rho[first]][trump]!=0)) {
4155
if ((posPoint->length[partner[first]][suit]!=0)||
4156
(posPoint->length[partner[first]][trump]==0))
4158
else if (posPoint->rankInSuit[rho[first]][trump]
4159
> posPoint->rankInSuit[partner[first]][trump])
4164
else { /* winnerHand is partner to first */
4166
if ((posPoint->length[rho[first]][suit]==0)&&
4167
(posPoint->length[rho[first]][trump]!=0))
4174
/* Leading suit differs from suit played by LHO */
4177
if (posPoint->length[partner[first]][leadSuit]!=0)
4179
else if (bitMapRank[mp->rank]>
4180
posPoint->rankInSuit[partner[first]][trump])
4182
else if ((posPoint->length[rho[first]][leadSuit]==0)
4183
&&(posPoint->length[rho[first]][trump]!=0)&&
4184
(posPoint->rankInSuit[rho[first]][trump] >
4185
posPoint->rankInSuit[partner[first]][trump]))
4188
else if (leadSuit!=trump) {
4190
/* Neither suit nor leadSuit is trump */
4192
if (posPoint->length[partner[first]][leadSuit]!=0) {
4193
if (posPoint->rankInSuit[rho[first]][leadSuit] >
4194
(posPoint->rankInSuit[partner[first]][leadSuit] |
4195
bitMapRank[posPoint->move[depth+1].rank]))
4197
else if ((posPoint->length[rho[first]][leadSuit]==0)
4198
&&(posPoint->length[rho[first]][trump]!=0))
4202
/* Partner to leading hand is void in leading suit */
4204
else if ((posPoint->length[rho[first]][leadSuit]==0)
4205
&&(posPoint->rankInSuit[rho[first]][trump]>
4206
posPoint->rankInSuit[partner[first]][trump]))
4208
else if ((posPoint->length[partner[first]][trump]==0)
4209
&&(posPoint->rankInSuit[rho[first]][leadSuit] >
4210
bitMapRank[posPoint->move[depth+1].rank]))
4214
/* Either no trumps or leadSuit is trump, side with
4215
highest rank in leadSuit wins */
4216
if (posPoint->rankInSuit[rho[first]][leadSuit] >
4217
(posPoint->rankInSuit[partner[first]][leadSuit] |
4218
bitMapRank[posPoint->move[depth+1].rank]))
4224
kk=posPoint->rankInSuit[partner[first]][leadSuit];
4225
ll=posPoint->rankInSuit[rho[first]][leadSuit];
4226
k=kk & (-kk); l=ll & (-ll); /* Only least significant 1 bit of
4227
bit map ranks for partner and RHO. */
4230
if (!notVoidInSuit) {
4231
suitCount=posPoint->length[q][suit];
4232
suitAdd=(suitCount<<6)/(43/*36*/);
4234
/* Discourage suit discard if 2nd highest card becomes singleton. */
4236
if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
4240
weight=25/*23*/-(mp->rank)+suitAdd;
4242
weight=60-(mp->rank)+suitAdd; /* Better discard than ruff since rho
4245
else if (k > bitMapRank[mp->rank])
4246
weight=40/*41*/+rRank;
4248
/* If lowest card for partner to leading hand
4249
is higher than lho played card, playing as low as
4250
possible will give the cheapest win */
4252
else if ((ll > bitMapRank[posPoint->move[depth+1].rank])&&
4253
(posPoint->rankInSuit[first][leadSuit] > ll))
4254
weight=37/*40*/+rRank;
4256
/* If rho has a card in the leading suit that
4257
is higher than the trick leading card but lower
4258
than the highest rank of the leading hand, then
4259
lho playing the lowest card will be the cheapest
4262
else if (mp->rank > posPoint->move[depth+1].rank) {
4263
if (bitMapRank[mp->rank] < ll)
4264
weight=75-(mp->rank); /* If played card is lower than any of the cards of
4265
rho, it will be the cheapest win */
4266
else if (bitMapRank[mp->rank] > kk)
4267
weight=70-(mp->rank); /* If played card is higher than any cards at partner
4268
of the leading hand, rho can play low, under the
4269
condition that he has a lower card than lho played */
4272
weight=62/*63*//*60*/-(mp->rank);
4274
weight=48/*45*/-(mp->rank);
4277
else if (posPoint->length[rho[first]][leadSuit]>0) {
4279
weight=47/*50*/-(mp->rank); /* Playing a card in a sequence may promote a winner */
4282
weight=45-(mp->rank);
4285
weight=43/*45*/-(mp->rank);
4288
if (!notVoidInSuit) {
4289
suitCount=posPoint->length[q][suit];
4290
suitAdd=(suitCount<<6)/(33/*36*/);
4292
/* Discourage suit discard if 2nd highest card becomes singleton. */
4294
if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
4298
weight=16/*15*/-(mp->rank)+suitAdd; /* Ruffing is preferred, makes the trick
4299
costly for the opponents */
4302
weight=-6-(mp->rank)+suitAdd;
4304
else if ((k > bitMapRank[mp->rank])||
4305
(l > bitMapRank[mp->rank]))
4306
weight=-7/*-9*/+rRank;
4308
/* If lowest rank for either partner to leading hand
4309
or rho is higher than played card for lho,
4310
lho should play as low card as possible */
4312
else if (mp->rank > posPoint->move[depth+1].rank) {
4314
weight=19/*19*/-(mp->rank);
4316
weight=10-(mp->rank);
4325
leadSuit=posPoint->move[depth+2].suit;
4326
if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId)) {
4327
if (suit==leadSuit) {
4328
if (leadSuit!=trump) {
4329
if (((posPoint->length[rho[first]][suit]!=0)||
4330
(posPoint->length[rho[first]][trump]==0))&&
4331
(bitMapRank[mp->rank] >
4332
posPoint->rankInSuit[rho[first]][suit]))
4335
else if (bitMapRank[mp->rank] >
4336
posPoint->rankInSuit[rho[first]][suit])
4339
else { /* Suit is trump */
4340
if (posPoint->length[rho[first]][leadSuit]==0) {
4341
if (bitMapRank[mp->rank] >
4342
posPoint->rankInSuit[rho[first]][trump])
4349
else if (posPoint->high[depth+1]==first) {
4350
if (posPoint->length[rho[first]][leadSuit]!=0) {
4351
if (posPoint->rankInSuit[rho[first]][leadSuit]
4352
< bitMapRank[posPoint->move[depth+2].rank])
4355
else if (leadSuit==trump)
4357
else if ((leadSuit!=trump) &&
4358
(posPoint->length[rho[first]][trump]==0))
4363
if (!notVoidInSuit) {
4364
suitCount=posPoint->length[q][suit];
4365
suitAdd=(suitCount<<6)/(48/*36*/);
4367
/* Discourage suit discard if 2nd highest card becomes singleton. */
4369
if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
4372
if (posPoint->high[depth+1]==first) {
4374
weight=30-(mp->rank)+suitAdd; /* Ruffs partner's winner */
4376
weight=60-(mp->rank)+suitAdd;
4378
else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId))
4380
/* Own hand on top by ruffing */
4382
weight=70-(mp->rank)+suitAdd;
4385
weight=60-(mp->rank);
4388
if (!notVoidInSuit) {
4389
suitCount=posPoint->length[q][suit];
4390
suitAdd=(suitCount<<6)/36;
4392
/* Discourage suit discard if 2nd highest card becomes singleton. */
4394
if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
4397
if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId))
4399
/* Own hand on top by ruffing */
4401
weight=40-(mp->rank)+suitAdd;
4402
else if (suit==trump)
4404
/* Discard a trump but still losing */
4406
weight=-/*33*/36+rRank+suitAdd;
4408
weight=-(mp->rank)+suitAdd;
4411
k=posPoint->rankInSuit[rho[first]][suit];
4412
if ((k & (-k)) > bitMapRank[mp->rank])
4414
/* If least bit map rank of RHO to lead hand is higher than bit map rank
4415
of current card move. */
4419
else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId)) {
4421
/* If current card move is highest so far. */
4423
if (mp->rank==posPoint->secondBest[leadSuit].rank)
4425
else if (mp->sequence)
4426
weight=21/*20*/-(mp->rank);
4428
weight=10-(mp->rank);
4431
weight=-10-(mp->rank);
4438
if (!notVoidInSuit) {
4439
suitCount=posPoint->length[q][suit];
4440
suitAdd=(suitCount<<6)/(24/*36*/);
4441
if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q))
4442
suitAdd-=(2/*0*//*2*/);
4444
if ((posPoint->high[depth+1])==lho[first]) {
4446
/* If the current winning move is given by the partner */
4450
/* Ruffing partners winner? */
4452
weight=2/*17*/-(mp->rank)+suitAdd;
4454
weight=25-(mp->rank)+suitAdd;
4456
else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId))
4458
/* Own hand ruffs */
4460
weight=33/*27*/+rRank+suitAdd;
4461
else if (suit==trump)
4464
weight=14-(mp->rank)+suitAdd;
4466
else if ((posPoint->high[depth+1])==(lho[first])) {
4468
/* If the current winning move is given by the partner */
4472
/* Ruffs partners winner */
4478
else if (WinningMove(mp, &(posPoint->move[depth+1]),trump,thrId))
4480
/* If present move is superior to current winning move and the
4481
current winning move is not given by the partner */
4486
/* If present move is not superior to current winning move and the
4487
current winning move is not given by the partner */
4491
/* Ruffs but still loses */
4504
/*void shellSort(int n, int depth) {
4506
struct moveType temp;
4509
if (movePly[depth].move[0].weight<movePly[depth].move[1].weight) {
4510
temp=movePly[depth].move[0];
4511
movePly[depth].move[0]=movePly[depth].move[1];
4512
movePly[depth].move[1]=temp;
4518
for (gap=n>>1; gap>0; gap>>=1)
4519
for (i=gap; i<n; i++)
4520
for (j=i-gap; j>=0 && movePly[depth].move[j].weight<
4521
movePly[depth].move[j+gap].weight; j-=gap) {
4522
temp=movePly[depth].move[j];
4523
movePly[depth].move[j]=movePly[depth].move[j+gap];
4524
movePly[depth].move[j+gap]=temp;
4529
/*void shellSort(int n, int depth)
4531
int i, j, increment;
4532
struct moveType temp;
4535
if (movePly[depth].move[0].weight<movePly[depth].move[1].weight) {
4536
temp=movePly[depth].move[0];
4537
movePly[depth].move[0]=movePly[depth].move[1];
4538
movePly[depth].move[1]=temp;
4545
while (increment > 0)
4547
for (i=0; i < n; i++)
4550
temp = movePly[depth].move[i];
4551
while ((j >= increment) && (movePly[depth].move[j-increment].weight < temp.weight))
4553
movePly[depth].move[j] = movePly[depth].move[j - increment];
4556
movePly[depth].move[j] = temp;
4558
if ((increment>>1) != 0)
4560
else if (increment == 1)
4569
/*void InsertSort(int n, int depth, struct movePlyType *mply, int thrId) {
4571
struct moveType a, temp;
4574
if (mply->move[0].weight<mply->move[1].weight) {
4576
mply->move[0]=mply->move[1];
4585
for (i=1; i<=n-1; i++)
4586
if (mply->move[i].weight>a.weight) {
4592
for (i=2; i<=n-1; i++) {
4595
while (a.weight>mply->move[j-1].weight) {
4596
mply->move[j]=mply->move[j-1];
4605
/*void InsertSort(int n, int depth) {
4610
if (movePly[depth].move[0].weight<movePly[depth].move[1].weight) {
4611
a=movePly[depth].move[0];
4612
movePly[depth].move[0]=movePly[depth].move[1];
4613
movePly[depth].move[1]=a;
4619
for (j=1; j<=n-1; j++) {
4620
a=movePly[depth].move[j];
4622
while ((i>=0)&&(movePly[depth].move[i].weight<a.weight)) {
4623
movePly[depth].move[i+1]=movePly[depth].move[i];
4626
movePly[depth].move[i+1]=a;
4630
void MergeSort(int n, struct moveType *a) {
4634
CMP_SWAP(0, 1); CMP_SWAP(2, 3); CMP_SWAP(4, 5); CMP_SWAP(6, 7); CMP_SWAP(8, 9); CMP_SWAP(10, 11);
4635
CMP_SWAP(1, 3); CMP_SWAP(5, 7); CMP_SWAP(9, 11);
4636
CMP_SWAP(0, 2); CMP_SWAP(4, 6); CMP_SWAP(8, 10);
4637
CMP_SWAP(1, 2); CMP_SWAP(5, 6); CMP_SWAP(9, 10);
4638
CMP_SWAP(1, 5); CMP_SWAP(6, 10);
4641
CMP_SWAP(1, 5); CMP_SWAP(6, 10);
4642
CMP_SWAP(0, 4); CMP_SWAP(7, 11);
4645
CMP_SWAP(0, 4); CMP_SWAP(7, 11);
4646
CMP_SWAP(1, 4); CMP_SWAP(7, 10);
4648
CMP_SWAP(2, 3); CMP_SWAP(8, 9);
4649
CMP_SWAP(2, 4); CMP_SWAP(7, 9);
4650
CMP_SWAP(3, 5); CMP_SWAP(6, 8);
4651
CMP_SWAP(3, 4); CMP_SWAP(5, 6); CMP_SWAP(7, 8);
4654
CMP_SWAP(0, 1); CMP_SWAP(2, 3); CMP_SWAP(4, 5); CMP_SWAP(6, 7); CMP_SWAP(8, 9);
4655
CMP_SWAP(1, 3); CMP_SWAP(5, 7);
4656
CMP_SWAP(0, 2); CMP_SWAP(4, 6); CMP_SWAP(8, 10);
4657
CMP_SWAP(1, 2); CMP_SWAP(5, 6); CMP_SWAP(9, 10);
4658
CMP_SWAP(1, 5); CMP_SWAP(6, 10);
4661
CMP_SWAP(1, 5); CMP_SWAP(6, 10);
4666
CMP_SWAP(1, 4); CMP_SWAP(7, 10);
4668
CMP_SWAP(2, 3); CMP_SWAP(8, 9);
4669
CMP_SWAP(2, 4); CMP_SWAP(7, 9);
4670
CMP_SWAP(3, 5); CMP_SWAP(6, 8);
4671
CMP_SWAP(3, 4); CMP_SWAP(5, 6); CMP_SWAP(7, 8);
4675
CMP_SWAP(0, 4); CMP_SWAP(5, 9);
4678
CMP_SWAP(0, 3); CMP_SWAP(6, 9);
4680
CMP_SWAP(0, 1); CMP_SWAP(3, 6); CMP_SWAP(8, 9);
4682
CMP_SWAP(0, 2); CMP_SWAP(4, 8);
4683
CMP_SWAP(1, 5); CMP_SWAP(7, 9);
4684
CMP_SWAP(1, 2); CMP_SWAP(3, 4); CMP_SWAP(5, 6); CMP_SWAP(7, 8);
4685
CMP_SWAP(1, 3); CMP_SWAP(6, 8);
4686
CMP_SWAP(2, 4); CMP_SWAP(5, 7);
4687
CMP_SWAP(2, 3); CMP_SWAP(6, 7);
4693
CMP_SWAP(0, 1); CMP_SWAP(3, 4); CMP_SWAP(6, 7);
4694
CMP_SWAP(1, 2); CMP_SWAP(4, 5); CMP_SWAP(7, 8);
4695
CMP_SWAP(0, 1); CMP_SWAP(3, 4); CMP_SWAP(6, 7);
4705
CMP_SWAP(1, 3); CMP_SWAP(5, 7);
4709
CMP_SWAP(2, 3); CMP_SWAP(5, 6);
4712
CMP_SWAP(0, 1); CMP_SWAP(2, 3); CMP_SWAP(4, 5); CMP_SWAP(6, 7);
4713
CMP_SWAP(0, 2); CMP_SWAP(4, 6); CMP_SWAP(1, 3); CMP_SWAP(5, 7);
4714
CMP_SWAP(1, 2); CMP_SWAP(5, 6); CMP_SWAP(0, 4); CMP_SWAP(1, 5);
4715
CMP_SWAP(2, 6); CMP_SWAP(3, 7); CMP_SWAP(2, 4); CMP_SWAP(3, 5);
4716
CMP_SWAP(1, 2); CMP_SWAP(3, 4); CMP_SWAP(5, 6);
4719
CMP_SWAP(0, 1); CMP_SWAP(2, 3); CMP_SWAP(4, 5);
4720
CMP_SWAP(0, 2); CMP_SWAP(4, 6);
4722
CMP_SWAP(1, 2); CMP_SWAP(5, 6);
4723
CMP_SWAP(0, 4); CMP_SWAP(1, 5); CMP_SWAP(2, 6);
4724
CMP_SWAP(2, 4); CMP_SWAP(3, 5);
4725
CMP_SWAP(1, 2); CMP_SWAP(3, 4); CMP_SWAP(5, 6);
4728
CMP_SWAP(0, 1); CMP_SWAP(2, 3); CMP_SWAP(4, 5);
4732
CMP_SWAP(0, 4); CMP_SWAP(1, 5);
4733
CMP_SWAP(2, 4); CMP_SWAP(3, 5);
4734
CMP_SWAP(1, 2); CMP_SWAP(3, 4);
4737
CMP_SWAP(0, 1); CMP_SWAP(2, 3);
4743
CMP_SWAP(1, 2); CMP_SWAP(3, 4);
4746
CMP_SWAP(0, 1); CMP_SWAP(2, 3);
4760
for (int i = 1; i < n; i++)
4762
struct moveType tmp = a[i];
4764
for (; j && tmp.weight > a[j - 1].weight ; --j)
4775
int AdjustMoveList(int thrId) {
4776
int k, r, n, rank, suit;
4778
for (k=1; k<=13; k++) {
4779
suit=localVar[thrId].forbiddenMoves[k].suit;
4780
rank=localVar[thrId].forbiddenMoves[k].rank;
4781
for (r=0; r<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; r++) {
4782
if ((suit==localVar[thrId].movePly[localVar[thrId].iniDepth].move[r].suit)&&
4783
(rank!=0)&&(rank==localVar[thrId].movePly[localVar[thrId].iniDepth].move[r].rank)) {
4784
/* For the forbidden move r: */
4785
for (n=r; n<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; n++)
4786
localVar[thrId].movePly[localVar[thrId].iniDepth].move[n]=
4787
localVar[thrId].movePly[localVar[thrId].iniDepth].move[n+1];
4788
localVar[thrId].movePly[localVar[thrId].iniDepth].last--;
4792
return localVar[thrId].movePly[localVar[thrId].iniDepth].last+1;
4796
int InvBitMapRank(unsigned short bitMap) {
4799
case 0x1000: return 14;
4800
case 0x0800: return 13;
4801
case 0x0400: return 12;
4802
case 0x0200: return 11;
4803
case 0x0100: return 10;
4804
case 0x0080: return 9;
4805
case 0x0040: return 8;
4806
case 0x0020: return 7;
4807
case 0x0010: return 6;
4808
case 0x0008: return 5;
4809
case 0x0004: return 4;
4810
case 0x0002: return 3;
4811
case 0x0001: return 2;
4816
int InvWinMask(int mask) {
4819
case 0x01000000: return 1;
4820
case 0x00400000: return 2;
4821
case 0x00100000: return 3;
4822
case 0x00040000: return 4;
4823
case 0x00010000: return 5;
4824
case 0x00004000: return 6;
4825
case 0x00001000: return 7;
4826
case 0x00000400: return 8;
4827
case 0x00000100: return 9;
4828
case 0x00000040: return 10;
4829
case 0x00000010: return 11;
4830
case 0x00000004: return 12;
4831
case 0x00000001: return 13;
4837
inline int WinningMove(struct moveType * mvp1, struct moveType * mvp2, int trump, int thrId) {
4838
/* Return TRUE if move 1 wins over move 2, with the assumption that
4839
move 2 is the presently winning card of the trick */
4841
if (mvp1->suit==mvp2->suit) {
4842
if ((mvp1->rank)>(mvp2->rank))
4847
else if ((mvp1->suit)==trump)
4854
inline int WinningMoveNT(struct moveType * mvp1, struct moveType * mvp2, int thrId) {
4855
/* Return TRUE if move 1 wins over move 2, with the assumption that
4856
move 2 is the presently winning card of the trick */
4858
if (mvp1->suit==mvp2->suit) {
4859
if ((mvp1->rank)>(mvp2->rank))
4869
struct nodeCardsType * CheckSOP(struct pos * posPoint, struct nodeCardsType
4870
* nodep, int target, int tricks, int * result, int *value, int thrId) {
4871
/* Check SOP if it matches the
4872
current position. If match, pointer to the SOP node is returned and
4873
result is set to TRUE, otherwise pointer to SOP node is returned
4874
and result set to FALSE. */
4877
if (localVar[thrId].nodeTypeStore[0]==MAXNODE) {
4878
if (nodep->lbound==-1) { /* This bound values for
4879
this leading hand has not yet been determined */
4883
else if ((posPoint->tricksMAX + nodep->lbound)>=target) {
4888
else if ((posPoint->tricksMAX + nodep->ubound)<target) {
4895
if (nodep->ubound==-1) { /* This bound values for
4896
this leading hand has not yet been determined */
4900
else if ((posPoint->tricksMAX + (tricks + 1 - nodep->ubound))>=target) {
4905
else if ((posPoint->tricksMAX + (tricks + 1 - nodep->lbound))<target) {
4913
return nodep; /* No matching node was found */
4917
struct nodeCardsType * UpdateSOP(struct pos * posPoint, struct nodeCardsType
4919
/* Update SOP node with new values for upper and lower
4922
if ((posPoint->lbound > nodep->lbound) ||
4923
(nodep->lbound==-1))
4924
nodep->lbound=posPoint->lbound;
4925
if ((posPoint->ubound < nodep->ubound) ||
4926
(nodep->ubound==-1))
4927
nodep->ubound=posPoint->ubound;
4929
nodep->bestMoveSuit=posPoint->bestMoveSuit;
4930
nodep->bestMoveRank=posPoint->bestMoveRank;
4936
struct nodeCardsType * FindSOP(struct pos * posPoint,
4937
struct winCardType * nodeP, int firstHand,
4938
int target, int tricks, int * valp, int thrId) {
4939
struct nodeCardsType * sopP;
4940
struct winCardType * np;
4944
while ((np!=NULL)&&(s<4)) {
4945
if ((np->winMask & posPoint->orderSet[s])==
4947
/* Winning rank set fits position */
4949
sopP=CheckSOP(posPoint, np->first, target, tricks, &res, valp, thrId);
4954
if (np->next!=NULL) {
4962
while (np->next==NULL) {
4965
if (np==NULL) /* Previous node is header node? */
4978
if (np->next!=NULL) {
4986
while (np->next==NULL) {
4989
if (np==NULL) /* Previous node is header node? */
5000
struct nodeCardsType * BuildPath(struct pos * posPoint,
5001
struct posSearchType *nodep, int * result, int thrId) {
5002
/* If result is TRUE, a new SOP has been created and BuildPath returns a
5003
pointer to it. If result is FALSE, an existing SOP is used and BuildPath
5004
returns a pointer to the SOP */
5007
struct winCardType * np, * p2, /* * sp2,*/ * nprev, * fnp, *pnp;
5008
struct winCardType temp;
5009
struct nodeCardsType * sopP=0, * p/*, * sp*/;
5011
np=nodep->posSearchPoint;
5015
/* If winning node has a card that equals the next winning card deduced
5016
from the position, then there already exists a (partial) path */
5018
if (np==NULL) { /* There is no winning list created yet */
5019
/* Create winning nodes */
5020
p2=&localVar[thrId].winCards[localVar[thrId].winSetSize];
5025
nodep->posSearchPoint=p2;
5026
p2->winMask=posPoint->winMask[suit];
5027
p2->orderSet=posPoint->winOrderSet[suit];
5029
np=p2; /* Latest winning node */
5032
p2=&localVar[thrId].winCards[localVar[thrId].winSetSize];
5038
p2->winMask=posPoint->winMask[suit];
5039
p2->orderSet=posPoint->winOrderSet[suit];
5041
np=p2; /* Latest winning node */
5044
p=&localVar[thrId].nodeCards[localVar[thrId].nodeSetSize];
5050
else { /* Winning list exists */
5051
while (1) { /* Find all winning nodes that correspond to current
5054
while (1) { /* Find node amongst alternatives */
5055
if ((np->winMask==posPoint->winMask[suit])&&
5056
(np->orderSet==posPoint->winOrderSet[suit])) {
5057
/* Part of path found */
5070
sopP=UpdateSOP(posPoint, np->first);
5072
if (np->prevWin!=NULL) {
5077
fnp=nodep->posSearchPoint;
5079
temp.orderSet=np->orderSet;
5080
temp.winMask=np->winMask;
5081
temp.first=np->first;
5082
temp.nextWin=np->nextWin;
5083
np->orderSet=fnp->orderSet;
5084
np->winMask=fnp->winMask;
5085
np->first=fnp->first;
5086
np->nextWin=fnp->nextWin;
5087
fnp->orderSet=temp.orderSet;
5088
fnp->winMask=temp.winMask;
5089
fnp->first=temp.first;
5090
fnp->nextWin=temp.nextWin;
5096
np=np->nextWin; /* Find next winning node */
5101
break; /* Node was not found */
5102
} /* End outer while */
5104
/* Create additional node, coupled to existing node(s) */
5105
p2=&localVar[thrId].winCards[localVar[thrId].winSetSize];
5109
p2->next=nprev->nextWin;
5113
p2->next=nodep->posSearchPoint;
5114
nodep->posSearchPoint=p2;
5117
p2->winMask=posPoint->winMask[suit];
5118
p2->orderSet=posPoint->winOrderSet[suit];
5120
np=p2; /* Latest winning node */
5123
/* Rest of path must be created */
5125
p2=&localVar[thrId].winCards[localVar[thrId].winSetSize];
5130
p2->winMask=posPoint->winMask[suit];
5131
p2->orderSet=posPoint->winOrderSet[suit];
5134
np=p2; /* Latest winning node */
5138
/* All winning nodes in SOP have been traversed and new nodes created */
5139
p=&localVar[thrId].nodeCards[localVar[thrId].nodeSetSize];
5148
struct posSearchType * SearchLenAndInsert(struct posSearchType
5149
* rootp, long long key, int insertNode, int *result, int thrId) {
5150
/* Search for node which matches with the suit length combination
5151
given by parameter key. If no such node is found, NULL is
5152
returned if parameter insertNode is FALSE, otherwise a new
5153
node is inserted with suitLengths set to key, the pointer to
5154
this node is returned.
5155
The algorithm used is defined in Knuth "The art of computer
5156
programming", vol.3 "Sorting and searching", 6.2.2 Algorithm T,
5159
struct posSearchType *np, *p, *sp;
5162
sp=&localVar[thrId].posSearch[localVar[thrId].lenSetSize];
5166
if (key==np->suitLengths) {
5170
else if (key < np->suitLengths) {
5173
else if (insertNode) {
5177
p->posSearchPoint=NULL;
5179
p->left=NULL; p->right=NULL;
5188
else { /* key > suitLengths */
5189
if (np->right!=NULL)
5191
else if (insertNode) {
5195
p->posSearchPoint=NULL;
5197
p->left=NULL; p->right=NULL;
5211
void BuildSOP(struct pos * posPoint, int tricks, int firstHand, int target,
5212
int depth, int scoreFlag, int score, int thrId) {
5213
int ss, hh, res, wm;
5214
unsigned short int w;
5215
unsigned short int temp[4][4];
5216
unsigned short int aggr[4];
5217
struct nodeCardsType * cardsP;
5218
struct posSearchType * np;
5219
long long suitLengths;
5222
int k, mcurrent, rr;
5223
mcurrent=localVar[thrId].movePly[depth].current;
5226
for (ss=0; ss<=3; ss++) {
5227
w=posPoint->winRanks[depth][ss];
5229
posPoint->winMask[ss]=0;
5230
posPoint->winOrderSet[ss]=0;
5231
posPoint->leastWin[ss]=0;
5232
for (hh=0; hh<=3; hh++)
5236
w=w & (-w); /* Only lowest win */
5237
for (hh=0; hh<=3; hh++)
5238
temp[hh][ss]=posPoint->rankInSuit[hh][ss] & (-w);
5241
for (hh=0; hh<=3; hh++)
5242
aggr[ss]=aggr[ss] | temp[hh][ss];
5243
posPoint->winMask[ss]=localVar[thrId].rel[aggr[ss]].winMask[ss];
5244
posPoint->winOrderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss];
5245
wm=posPoint->winMask[ss];
5247
posPoint->leastWin[ss]=InvWinMask(wm);
5253
if (localVar[thrId].nodeTypeStore[0]==MAXNODE) {
5254
posPoint->ubound=tricks+1;
5255
posPoint->lbound=target-posPoint->tricksMAX;
5258
posPoint->ubound=tricks+1-target+posPoint->tricksMAX;
5263
if (localVar[thrId].nodeTypeStore[0]==MAXNODE) {
5264
posPoint->ubound=target-posPoint->tricksMAX-1;
5268
posPoint->ubound=tricks+1;
5269
posPoint->lbound=tricks+1-target+posPoint->tricksMAX+1;
5274
for (ss=0; ss<=2; ss++)
5275
for (hh=0; hh<=3; hh++) {
5277
suitLengths|=posPoint->length[hh][ss];
5280
np=SearchLenAndInsert(localVar[thrId].rootnp[tricks][firstHand],
5281
suitLengths, TRUE, &res, thrId);
5283
cardsP=BuildPath(posPoint, np, &res, thrId);
5285
cardsP->ubound=posPoint->ubound;
5286
cardsP->lbound=posPoint->lbound;
5287
if (((localVar[thrId].nodeTypeStore[firstHand]==MAXNODE)&&(scoreFlag))||
5288
((localVar[thrId].nodeTypeStore[firstHand]==MINNODE)&&(!scoreFlag))) {
5289
cardsP->bestMoveSuit=localVar[thrId].bestMove[depth].suit;
5290
cardsP->bestMoveRank=localVar[thrId].bestMove[depth].rank;
5293
cardsP->bestMoveSuit=0;
5294
cardsP->bestMoveRank=0;
5296
posPoint->bestMoveSuit=localVar[thrId].bestMove[depth].suit;
5297
posPoint->bestMoveRank=localVar[thrId].bestMove[depth].rank;
5298
for (ss=0; ss<=3; ss++)
5299
cardsP->leastWin[ss]=posPoint->leastWin[ss];
5307
if ((res) && (ttCollect) && (!suppressTTlog)) {
5308
fprintf(localVar[thrId].fp7, "cardsP=%d\n", (int)cardsP);
5309
fprintf(localVar[thrId].fp7, "nodeSetSize=%d\n", localVar[thrId].nodeSetSize);
5310
fprintf(localVar[thrId].fp7, "ubound=%d\n", cardsP->ubound);
5311
fprintf(localVar[thrId].fp7, "lbound=%d\n", cardsP->lbound);
5312
fprintf(localVar[thrId].fp7, "target=%d\n", target);
5313
fprintf(localVar[thrId].fp7, "first=%c nextFirst=%c\n",
5314
cardHand[posPoint->first[depth]], cardHand[posPoint->first[depth-1]]);
5315
fprintf(localVar[thrId].fp7, "bestMove: suit=%c rank=%c\n", cardSuit[localVar[thrId].bestMove[depth].suit],
5316
cardRank[localVar[thrId].bestMove[depth].rank]);
5317
fprintf(localVar[thrId].fp7, "\n");
5318
fprintf(localVar[thrId].fp7, "Last trick:\n");
5319
fprintf(localVar[thrId].fp7, "1st hand=%c\n", cardHand[posPoint->first[depth+3]]);
5320
for (k=3; k>=0; k--) {
5321
mcurrent=localVar[thrId].movePly[depth+k+1].current;
5322
fprintf(localVar[thrId].fp7, "suit=%c rank=%c\n",
5323
cardSuit[localVar[thrId].movePly[depth+k+1].move[mcurrent].suit],
5324
cardRank[localVar[thrId].movePly[depth+k+1].move[mcurrent].rank]);
5326
fprintf(localVar[thrId].fp7, "\n");
5327
for (hh=0; hh<=3; hh++) {
5328
fprintf(localVar[thrId].fp7, "hand=%c\n", cardHand[hh]);
5329
for (ss=0; ss<=3; ss++) {
5330
fprintf(localVar[thrId].fp7, "suit=%c", cardSuit[ss]);
5331
for (rr=14; rr>=2; rr--)
5332
if (posPoint->rankInSuit[hh][ss] & bitMapRank[rr])
5333
fprintf(localVar[thrId].fp7, " %c", cardRank[rr]);
5334
fprintf(localVar[thrId].fp7, "\n");
5336
fprintf(localVar[thrId].fp7, "\n");
5338
fprintf(localVar[thrId].fp7, "\n");
5344
int CheckDeal(struct moveType * cardp, int thrId) {
5346
unsigned short int temp[4][4];
5348
for (h=0; h<=3; h++)
5349
for (s=0; s<=3; s++)
5350
temp[h][s]=localVar[thrId].game.suit[h][s];
5352
/* Check that all ranks appear only once within the same suit. */
5353
for (s=0; s<=3; s++)
5354
for (k=2; k<=14; k++) {
5356
for (h=0; h<=3; h++) {
5357
if ((temp[h][s] & bitMapRank[k])!=0) {
5373
int NextMove(struct pos *posPoint, int depth, struct movePlyType *mply, int thrId) {
5374
/* Returns TRUE if at least one move remains to be
5375
searched, otherwise FALSE is returned. */
5377
unsigned short int lw;
5379
struct moveType currMove;
5381
mcurrent=mply->current;
5382
currMove=mply->move[mcurrent];
5384
if (localVar[thrId].lowestWin[depth][currMove.suit]==0) {
5385
/* A small card has not yet been identified for this suit. */
5386
lw=posPoint->winRanks[depth][currMove.suit];
5388
lw=lw & (-lw); /* LSB */
5391
if (bitMapRank[currMove.rank]<lw) {
5392
/* The current move has a small card. */
5393
localVar[thrId].lowestWin[depth][currMove.suit]=lw;
5394
while (mply->current <= (mply->last-1)) {
5396
mcurrent=mply->current;
5397
if (bitMapRank[mply->move[mcurrent].rank] >=
5398
localVar[thrId].lowestWin[depth][mply->move[mcurrent].suit])
5404
while (mply->current <= (mply->last-1)) {
5406
mcurrent=mply->current;
5407
suit=mply->move[mcurrent].suit;
5408
if ((currMove.suit==suit) || (bitMapRank[mply->move[mcurrent].rank] >=
5409
localVar[thrId].lowestWin[depth][suit]))
5416
while (mply->current<=(mply->last-1)) {
5418
mcurrent=mply->current;
5419
if (bitMapRank[mply->move[mcurrent].rank] >=
5420
localVar[thrId].lowestWin[depth][mply->move[mcurrent].suit])
5428
int DumpInput(int errCode, struct deal dl, int target,
5429
int solutions, int mode) {
5433
unsigned short ranks[4][4];
5435
fp=fopen("dump.txt", "w");
5438
fprintf(fp, "Error code=%d\n", errCode);
5440
fprintf(fp, "Deal data:\n");
5442
fprintf(fp, "trump=%c\n", cardSuit[dl.trump]);
5444
fprintf(fp, "trump=N\n");
5445
fprintf(fp, "first=%c\n", cardHand[dl.first]);
5446
for (k=0; k<=2; k++)
5447
if (dl.currentTrickRank[k]!=0)
5448
fprintf(fp, "index=%d currentTrickSuit=%c currentTrickRank=%c\n",
5449
k, cardSuit[dl.currentTrickSuit[k]], cardRank[dl.currentTrickRank[k]]);
5450
for (i=0; i<=3; i++)
5451
for (j=0; j<=3; j++) {
5452
fprintf(fp, "index1=%d index2=%d remainCards=%d\n",
5453
i, j, dl.remainCards[i][j]);
5454
ranks[i][j]=dl.remainCards[i][/*3-*/j]>>2;
5457
fprintf(fp, "target=%d\n", target);
5458
fprintf(fp, "solutions=%d\n", solutions);
5459
fprintf(fp, "mode=%d\n", mode);
5461
PrintDeal(fp, ranks);
5466
void PrintDeal(FILE *fp, unsigned short ranks[][4]) {
5467
int i, count, ec[4], trickCount=0, s, r;
5468
for (i=0; i<=3; i++) {
5469
count=counttable[ranks[3][i]];
5474
trickCount=trickCount+count;
5477
for (s=0; s<=3; s++) {
5478
fprintf(fp, "\t%c ", cardSuit[s]);
5482
for (r=14; r>=2; r--)
5483
if ((ranks[0][s] & bitMapRank[r])!=0)
5484
fprintf(fp, "%c", cardRank[r]);
5488
for (s=0; s<=3; s++) {
5489
fprintf(fp, "%c ", cardSuit[s]);
5493
for (r=14; r>=2; r--)
5494
if ((ranks[3][s] & bitMapRank[r])!=0)
5495
fprintf(fp, "%c", cardRank[r]);
5498
fprintf(fp, "\t\%c ", cardSuit[s]);
5500
fprintf(fp, "\t\t\%c ", cardSuit[s]);
5504
for (r=14; r>=2; r--)
5505
if ((ranks[1][s] & bitMapRank[r])!=0)
5506
fprintf(fp, "%c", cardRank[r]);
5510
for (s=0; s<=3; s++) {
5511
fprintf(fp, "\t%c ", cardSuit[s]);
5515
for (r=14; r>=2; r--)
5516
if ((ranks[2][s] & bitMapRank[r])!=0)
5517
fprintf(fp, "%c", cardRank[r]);
5527
void Wipe(int thrId) {
5530
for (k=1; k<=localVar[thrId].wcount; k++) {
5531
if (localVar[thrId].pw[k])
5532
free(localVar[thrId].pw[k]);
5533
localVar[thrId].pw[k]=NULL;
5535
for (k=1; k<=localVar[thrId].ncount; k++) {
5536
if (localVar[thrId].pn[k])
5537
free(localVar[thrId].pn[k]);
5538
localVar[thrId].pn[k]=NULL;
5540
for (k=1; k<=localVar[thrId].lcount; k++) {
5541
if (localVar[thrId].pl[k])
5542
free(localVar[thrId].pl[k]);
5543
localVar[thrId].pl[k]=NULL;
5546
localVar[thrId].allocmem=localVar[thrId].summem;
5552
void AddWinSet(int thrId) {
5553
if (localVar[thrId].clearTTflag) {
5554
localVar[thrId].windex++;
5555
localVar[thrId].winSetSize=localVar[thrId].windex;
5556
/*localVar[thrId].fp2=fopen("dyn.txt", "a");
5557
fprintf(localVar[thrId].fp2, "windex=%d\n", windex);
5558
fclose(localVar[thrId].fp2);*/
5559
localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex];
5561
else if (localVar[thrId].winSetSize>=localVar[thrId].winSetSizeLimit) {
5562
/* The memory chunk for the winCards structure will be exceeded. */
5563
if ((localVar[thrId].allocmem+localVar[thrId].wmem)>localVar[thrId].maxmem) {
5564
/* Already allocated memory plus needed allocation overshot maxmem */
5565
localVar[thrId].windex++;
5566
localVar[thrId].winSetSize=localVar[thrId].windex;
5567
/*localVar[thrId].fp2=fopen("dyn.txt", "a");
5568
fprintf(localVar[thrId].fp2, "windex=%d\n", windex);
5569
fclose(localVar[thrId].fp2);*/
5570
localVar[thrId].clearTTflag=TRUE;
5571
localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex];
5574
localVar[thrId].wcount++; localVar[thrId].winSetSizeLimit=WSIZE;
5575
localVar[thrId].pw[localVar[thrId].wcount] =
5576
(struct winCardType *)calloc(localVar[thrId].winSetSizeLimit+1, sizeof(struct winCardType));
5577
if (localVar[thrId].pw[localVar[thrId].wcount]==NULL) {
5578
localVar[thrId].clearTTflag=TRUE;
5579
localVar[thrId].windex++;
5580
localVar[thrId].winSetSize=localVar[thrId].windex;
5581
localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex];
5584
localVar[thrId].allocmem+=(localVar[thrId].winSetSizeLimit+1)*sizeof(struct winCardType);
5585
localVar[thrId].winSetSize=0;
5586
localVar[thrId].winCards=localVar[thrId].pw[localVar[thrId].wcount];
5591
localVar[thrId].winSetSize++;
5595
void AddNodeSet(int thrId) {
5596
if (localVar[thrId].nodeSetSize>=localVar[thrId].nodeSetSizeLimit) {
5597
/* The memory chunk for the nodeCards structure will be exceeded. */
5598
if ((localVar[thrId].allocmem+localVar[thrId].nmem)>localVar[thrId].maxmem) {
5599
/* Already allocated memory plus needed allocation overshot maxmem */
5600
localVar[thrId].clearTTflag=TRUE;
5603
localVar[thrId].ncount++; localVar[thrId].nodeSetSizeLimit=NSIZE;
5604
localVar[thrId].pn[localVar[thrId].ncount] = (struct nodeCardsType *)calloc(localVar[thrId].nodeSetSizeLimit+1, sizeof(struct nodeCardsType));
5605
if (localVar[thrId].pn[localVar[thrId].ncount]==NULL) {
5606
localVar[thrId].clearTTflag=TRUE;
5609
localVar[thrId].allocmem+=(localVar[thrId].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType);
5610
localVar[thrId].nodeSetSize=0;
5611
localVar[thrId].nodeCards=localVar[thrId].pn[localVar[thrId].ncount];
5616
localVar[thrId].nodeSetSize++;
5620
void AddLenSet(int thrId) {
5621
if (localVar[thrId].lenSetSize>=localVar[thrId].lenSetSizeLimit) {
5622
/* The memory chunk for the posSearchType structure will be exceeded. */
5623
if ((localVar[thrId].allocmem+localVar[thrId].lmem)>localVar[thrId].maxmem) {
5624
/* Already allocated memory plus needed allocation overshot maxmem */
5625
localVar[thrId].clearTTflag=TRUE;
5628
localVar[thrId].lcount++; localVar[thrId].lenSetSizeLimit=LSIZE;
5629
localVar[thrId].pl[localVar[thrId].lcount] = (struct posSearchType *)calloc(localVar[thrId].lenSetSizeLimit+1, sizeof(struct posSearchType));
5630
if (localVar[thrId].pl[localVar[thrId].lcount]==NULL) {
5631
localVar[thrId].clearTTflag=TRUE;
5634
localVar[thrId].allocmem+=(localVar[thrId].lenSetSizeLimit+1)*sizeof(struct posSearchType);
5635
localVar[thrId].lenSetSize=0;
5636
localVar[thrId].posSearch=localVar[thrId].pl[localVar[thrId].lcount];
5641
localVar[thrId].lenSetSize++;
5649
void ReceiveTTstore(struct pos *posPoint, struct nodeCardsType * cardsP,
5650
int target, int depth, int thrId) {
5651
int tricksLeft, hh, ss, rr;
5652
/* Stores current position information and TT position value in table
5653
ttStore with current entry lastTTStore. Also stores corresponding
5654
information in log rectt.txt. */
5656
for (hh=0; hh<=3; hh++)
5657
for (ss=0; ss<=3; ss++)
5658
tricksLeft+=posPoint->length[hh][ss];
5659
tricksLeft=tricksLeft/4;
5660
ttStore[lastTTstore].tricksLeft=tricksLeft;
5661
ttStore[lastTTstore].cardsP=cardsP;
5662
ttStore[lastTTstore].first=posPoint->first[depth];
5663
if ((localVar[thrId].handToPlay==posPoint->first[depth])||
5664
(localVar[thrId].handToPlay==partner[posPoint->first[depth]])) {
5665
ttStore[lastTTstore].target=target-posPoint->tricksMAX;
5666
ttStore[lastTTstore].ubound=cardsP->ubound;
5667
ttStore[lastTTstore].lbound=cardsP->lbound;
5670
ttStore[lastTTstore].target=tricksLeft-
5671
target+posPoint->tricksMAX+1;
5673
for (hh=0; hh<=3; hh++)
5674
for (ss=0; ss<=3; ss++)
5675
ttStore[lastTTstore].suit[hh][ss]=
5676
posPoint->rankInSuit[hh][ss];
5677
localVar[thrId].fp11=fopen("rectt.txt", "a");
5678
if (lastTTstore<SEARCHSIZE) {
5679
fprintf(localVar[thrId].fp11, "lastTTstore=%d\n", lastTTstore);
5680
fprintf(localVar[thrId].fp11, "tricksMAX=%d\n", posPoint->tricksMAX);
5681
fprintf(localVar[thrId].fp11, "leftTricks=%d\n",
5682
ttStore[lastTTstore].tricksLeft);
5683
fprintf(localVar[thrId].fp11, "cardsP=%d\n",
5684
ttStore[lastTTstore].cardsP);
5685
fprintf(localVar[thrId].fp11, "ubound=%d\n",
5686
ttStore[lastTTstore].ubound);
5687
fprintf(localVar[thrId].fp11, "lbound=%d\n",
5688
ttStore[lastTTstore].lbound);
5689
fprintf(localVar[thrId].fp11, "first=%c\n",
5690
cardHand[ttStore[lastTTstore].first]);
5691
fprintf(localVar[thrId].fp11, "target=%d\n",
5692
ttStore[lastTTstore].target);
5693
fprintf(localVar[thrId].fp11, "\n");
5694
for (hh=0; hh<=3; hh++) {
5695
fprintf(localVar[thrId].fp11, "hand=%c\n", cardHand[hh]);
5696
for (ss=0; ss<=3; ss++) {
5697
fprintf(localVar[thrId].fp11, "suit=%c", cardSuit[ss]);
5698
for (rr=14; rr>=2; rr--)
5699
if (ttStore[lastTTstore].suit[hh][ss]
5701
fprintf(localVar[thrId].fp11, " %c", cardRank[rr]);
5702
fprintf(localVar[thrId].fp11, "\n");
5704
fprintf(localVar[thrId].fp11, "\n");
5707
fclose(localVar[thrId].fp11);
5713
HANDLE solveAllEvents[MAXNOOFTHREADS];
5714
struct paramType param;
5715
LONG volatile threadIndex;
5716
LONG volatile current;
5718
const long chunk = 4;
5720
DWORD CALLBACK SolveChunkDDtable (void *) {
5721
struct futureTricks fut[MAXNOOFBOARDS];
5725
thid=InterlockedIncrement(&threadIndex);
5727
while ((j=InterlockedExchangeAdd(¤t, chunk))<param.noOfBoards) {
5729
for (int k=0; k<chunk && j+k<param.noOfBoards; k++) {
5730
int res=SolveBoard(param.bop->deals[j+k], param.bop->target[j+k],
5731
param.bop->solutions[j+k], param.bop->mode[j+k],
5734
param.solvedp->solvedBoard[j+k]=fut[j+k];
5743
if (SetEvent(solveAllEvents[thid])==0) {
5744
int errCode=GetLastError();
5752
int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp) {
5755
DWORD solveAllWaitResult;
5761
if (bop->noOfBoards > MAXNOOFBOARDS)
5764
for (k=0; k<noOfCores; k++) {
5765
solveAllEvents[k]=CreateEvent(NULL, FALSE, FALSE, 0);
5766
if (solveAllEvents[k]==0) {
5767
errCode=GetLastError();
5772
param.bop=bop; param.solvedp=solvedp; param.noOfBoards=bop->noOfBoards;
5774
for (k=0; k<MAXNOOFBOARDS; k++)
5775
solvedp->solvedBoard[k].cards=0;
5777
for (k=0; k<noOfCores; k++) {
5778
res=QueueUserWorkItem(SolveChunkDDtable, NULL, WT_EXECUTELONGFUNCTION);
5780
errCode=GetLastError();
5785
solveAllWaitResult = WaitForMultipleObjects(noOfCores,
5786
solveAllEvents, TRUE, INFINITE);
5787
if (solveAllWaitResult!=WAIT_OBJECT_0) {
5788
errCode=GetLastError();
5792
for (k=0; k<noOfCores; k++) {
5793
CloseHandle(solveAllEvents[k]);
5796
/* Calculate number of solved boards. */
5798
solvedp->noOfBoards=0;
5799
for (k=0; k<MAXNOOFBOARDS; k++) {
5800
if (solvedp->solvedBoard[k].cards!=0)
5801
solvedp->noOfBoards++;
5810
DWORD CALLBACK SolveChunk (void *) {
5811
struct futureTricks fut[MAXNOOFBOARDS];
5815
thid=InterlockedIncrement(&threadIndex);
5817
while ((j=(InterlockedIncrement(¤t)-1))<param.noOfBoards) {
5819
int res=SolveBoard(param.bop->deals[j], param.bop->target[j],
5820
param.bop->solutions[j], param.bop->mode[j], &fut[j], thid);
5822
param.solvedp->solvedBoard[j]=fut[j];
5830
if (SetEvent(solveAllEvents[thid])==0) {
5831
int errCode=GetLastError();
5839
int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp) {
5842
DWORD solveAllWaitResult;
5848
if (bop->noOfBoards > MAXNOOFBOARDS)
5851
for (k=0; k<noOfCores; k++) {
5852
solveAllEvents[k]=CreateEvent(NULL, FALSE, FALSE, 0);
5853
if (solveAllEvents[k]==0) {
5854
errCode=GetLastError();
5859
param.bop=bop; param.solvedp=solvedp; param.noOfBoards=bop->noOfBoards;
5861
for (k=0; k<MAXNOOFBOARDS; k++)
5862
solvedp->solvedBoard[k].cards=0;
5864
for (k=0; k<noOfCores; k++) {
5865
res=QueueUserWorkItem(SolveChunk, NULL, WT_EXECUTELONGFUNCTION);
5867
errCode=GetLastError();
5872
solveAllWaitResult = WaitForMultipleObjects(noOfCores,
5873
solveAllEvents, TRUE, INFINITE);
5874
if (solveAllWaitResult!=WAIT_OBJECT_0) {
5875
errCode=GetLastError();
5879
for (k=0; k<noOfCores; k++) {
5880
CloseHandle(solveAllEvents[k]);
5883
/* Calculate number of solved boards. */
5885
solvedp->noOfBoards=0;
5886
for (k=0; k<MAXNOOFBOARDS; k++) {
5887
if (solvedp->solvedBoard[k].cards!=0)
5888
solvedp->noOfBoards++;
5897
int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp) {
5898
int k, i, res, chunk, fail;
5899
struct futureTricks fut[MAXNOOFBOARDS];
5903
if (bop->noOfBoards > MAXNOOFBOARDS)
5906
for (i=0; i<MAXNOOFBOARDS; i++)
5907
solvedp->solvedBoard[i].cards=0;
5909
omp_set_num_threads(noOfCores); /* Added after suggestion by Dirk Willecke. */
5911
#pragma omp parallel shared(bop, solvedp, chunk, fail) private(k)
5914
#pragma omp for schedule(dynamic, chunk)
5916
for (k=0; k<bop->noOfBoards; k++) {
5917
res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k],
5918
bop->mode[k], &fut[k], omp_get_thread_num());
5920
solvedp->solvedBoard[k]=fut[k];
5930
solvedp->noOfBoards=0;
5931
for (i=0; i<MAXNOOFBOARDS; i++) {
5932
if (solvedp->solvedBoard[i].cards!=0)
5933
solvedp->noOfBoards++;
5939
int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp) {
5940
int k, i, res, chunk, fail;
5941
struct futureTricks fut[MAXNOOFBOARDS];
5945
if (bop->noOfBoards > MAXNOOFBOARDS)
5948
for (i=0; i<MAXNOOFBOARDS; i++)
5949
solvedp->solvedBoard[i].cards=0;
5951
omp_set_num_threads(noOfCores); /* Added after suggestion by Dirk Willecke. */
5953
#pragma omp parallel shared(bop, solvedp, chunk, fail) private(k)
5956
#pragma omp for schedule(dynamic, chunk)
5958
for (k=0; k<bop->noOfBoards; k++) {
5959
res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k],
5960
bop->mode[k], &fut[k], omp_get_thread_num());
5962
solvedp->solvedBoard[k]=fut[k];
5972
solvedp->noOfBoards=0;
5973
for (i=0; i<MAXNOOFBOARDS; i++) {
5974
if (solvedp->solvedBoard[i].cards!=0)
5975
solvedp->noOfBoards++;
5982
int STDCALL CalcDDtable(struct ddTableDeal tableDeal, struct ddTableResults * tablep) {
5984
int h, s, k, ind, tr, first, res;
5987
struct solvedBoards solved;
5989
for (h=0; h<=3; h++)
5990
for (s=0; s<=3; s++)
5991
dl.remainCards[h][s]=tableDeal.cards[h][s];
5993
for (k=0; k<=2; k++) {
5994
dl.currentTrickRank[k]=0;
5995
dl.currentTrickSuit[k]=0;
5998
ind=0; bo.noOfBoards=20;
6000
for (tr=4; tr>=0; tr--)
6001
for (first=0; first<=3; first++) {
6006
bo.solutions[ind]=1;
6011
res=SolveAllBoards4(&bo, &solved);
6013
for (ind=0; ind<20; ind++) {
6014
tablep->resTable[bo.deals[ind].trump][rho[bo.deals[ind].first]]=
6015
13-solved.solvedBoard[ind].score[0];
6023
int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]) {
6024
int bp=0, first, card, hand, handRelFirst, suitInHand, h, s;
6025
int IsCard(char cardChar);
6027
for (h=0; h<=3; h++)
6028
for (s=0; s<=3; s++)
6029
remainCards[h][s]=0;
6031
while (((dealBuff[bp]!='W')&&(dealBuff[bp]!='N')&&
6032
(dealBuff[bp]!='E')&&(dealBuff[bp]!='S')&&
6033
(dealBuff[bp]!='w')&&(dealBuff[bp]!='n')&&
6034
(dealBuff[bp]!='e')&&(dealBuff[bp]!='s'))&&(bp<3))
6040
if ((dealBuff[bp]=='N')||(dealBuff[bp]=='n'))
6042
else if ((dealBuff[bp]=='E')||(dealBuff[bp]=='e'))
6044
else if ((dealBuff[bp]=='S')||(dealBuff[bp]=='s'))
6052
handRelFirst=0; suitInHand=0;
6054
while ((bp<80)&&(dealBuff[bp]!='\0')) {
6055
card=IsCard(dealBuff[bp]);
6062
if (handRelFirst==0)
6064
else if (handRelFirst==3)
6067
hand=handRelFirst+1;
6070
if (handRelFirst==0)
6072
else if (handRelFirst==1)
6075
hand=handRelFirst-2;
6078
if (handRelFirst==0)
6081
hand=handRelFirst-1;
6084
remainCards[hand][suitInHand]|=(bitMapRank[card]<<2);
6087
else if (dealBuff[bp]=='.')
6089
else if (dealBuff[bp]==' ') {
6098
int IsCard(char cardChar) {
6142
int STDCALL SolveBoardPBN(struct dealPBN dlpbn, int target,
6143
int solutions, int mode, struct futureTricks *futp, int thrId) {
6147
int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]);
6149
if (ConvertFromPBN(dlpbn.remainCards, dl.remainCards)!=1)
6152
for (k=0; k<=2; k++) {
6153
dl.currentTrickRank[k]=dlpbn.currentTrickRank[k];
6154
dl.currentTrickSuit[k]=dlpbn.currentTrickSuit[k];
6156
dl.first=dlpbn.first;
6157
dl.trump=dlpbn.trump;
6159
res=SolveBoard(dl, target, solutions, mode, futp, thrId);
6164
int STDCALL CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, struct ddTableResults * tablep) {
6165
struct ddTableDeal tableDeal;
6168
if (ConvertFromPBN(tableDealPBN.cards, tableDeal.cards)!=1)
6171
res=CalcDDtable(tableDeal, tablep);
6178
int STDCALL SolveAllBoards(struct boardsPBN *bop, struct solvedBoards *solvedp) {
6182
bo.noOfBoards=bop->noOfBoards;
6183
for (k=0; k<bop->noOfBoards; k++) {
6184
bo.mode[k]=bop->mode[k];
6185
bo.solutions[k]=bop->solutions[k];
6186
bo.target[k]=bop->target[k];
6187
bo.deals[k].first=bop->deals[k].first;
6188
bo.deals[k].trump=bop->deals[k].trump;
6189
for (i=0; i<=2; i++) {
6190
bo.deals[k].currentTrickSuit[i]=bop->deals[k].currentTrickSuit[i];
6191
bo.deals[k].currentTrickRank[i]=bop->deals[k].currentTrickRank[i];
6193
if (ConvertFromPBN(bop->deals[k].remainCards, bo.deals[k].remainCards)!=1)
6197
res=SolveAllBoards1(&bo, solvedp);
6204
int STDCALL CalcParPBN(struct ddTableDealPBN tableDealPBN,
6205
struct ddTableResults * tablep, int vulnerable, struct parResults *presp) {
6207
struct ddTableDeal tableDeal;
6208
int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]);
6209
int STDCALL CalcPar(struct ddTableDeal tableDeal, int vulnerable,
6210
struct ddTableResults * tablep, struct parResults *presp);
6212
if (ConvertFromPBN(tableDealPBN.cards, tableDeal.cards)!=1)
6215
res=CalcPar(tableDeal, vulnerable, tablep, presp);
6220
int STDCALL CalcPar(struct ddTableDeal tableDeal, int vulnerable,
6221
struct ddTableResults * tablep, struct parResults *presp) {
6225
int Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable);
6227
res=CalcDDtable(tableDeal, tablep);
6232
res=Par(tablep, presp, vulnerable);
6239
int Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable) {
6240
/* vulnerable 0: None 1: Both 2: NS 3: EW */
6242
/* The code for calculation of par score / contracts is based upon the
6243
perl code written by Matthew Kidd ACBLmerge. He has kindly given me permission
6244
to include a C++ adaptation in DDS. */
6246
/* The Par function computes the par result and contracts. */
6249
int denom_conv[5]={4, 0, 1, 2, 3};
6250
/* Preallocate for efficiency. These hold result from last direction
6251
(N-S or E-W) examined. */
6252
int i, j, k, m, isvul;
6253
int current_side, both_sides_once_flag, denom_max, max_lower;
6254
int new_score_flag, sc1, sc2;
6255
int prev_par_denom=0, prev_par_tricks=0;
6257
int ut, t1, t2, tt, score, dr, ke, tu, tu_max, t3, t4, n;
6258
struct par_suits_type par_suits[5];
6259
char contr_sep[2]={',','\0'};
6260
char temp[8], buff[4];
6262
int par_denom[2] = {-1, -1}; /* 0-4 = NT,S,H,D,C */
6263
int par_tricks[2] = {6, 6}; /* Initial "contract" beats 0 NT */
6264
int par_score[2] = {0, 0};
6265
int par_sacut[2] = {0, 0}; /* Undertricks for sacrifice (0 if not sac) */
6267
int rawscore(int denom, int tricks, int isvul);
6268
void IniSidesString(int dr, int i, int t1, int t2, char stri[]);
6269
int CalcMultiContracts(int max_lower, int tricks);
6271
/* Find best par result for N-S (i==0) or E-W (i==1). These will
6272
nearly always be the same, but when we have a "hot" situation
6273
they will not be. */
6275
for (i=0; i<=1; i++) {
6276
/* Start with the with the offensive side (current_side = 0) and alternate
6277
between sides seeking the to improve the result for the current side.*/
6279
current_side=0; both_sides_once_flag=0;
6282
/* Find best contract for current side that beats current contract.
6283
Choose highest contract if results are equal. */
6285
k=(i+current_side) % 2;
6287
isvul=((vulnerable==1)||(k ? (vulnerable==3) : (vulnerable==2)));
6290
prev_par_denom=par_denom[i];
6291
prev_par_tricks=par_tricks[i];
6293
/* Calculate tricks and score values and
6294
store them for each denomination in structure par_suits[5]. */
6296
for (j=0; j<=4; j++) {
6297
t1 = k ? tablep->resTable[denom_conv[j]][1] : tablep->resTable[denom_conv[j]][0];
6298
t2 = k ? tablep->resTable[denom_conv[j]][3] : tablep->resTable[denom_conv[j]][2];
6300
/* tt is the maximum number of tricks current side can take in
6302
par_suits[j].suit=j;
6303
par_suits[j].tricks=tt;
6304
if ((tt > par_tricks[i]) || ((tt == par_tricks[i]) &&
6305
(j < par_denom[i])))
6306
par_suits[j].score=rawscore(j, tt, isvul);
6308
par_suits[j].score=rawscore(-1, prev_par_tricks - tt, isvul);
6311
/* Sort the items in the par_suits structure with decreasing order of the
6312
values on the scores. */
6314
for (int s = 1; s < 5; s++) {
6315
struct par_suits_type tmp = par_suits[s];
6317
for (; r && tmp.score > par_suits[r - 1].score ; --r)
6318
par_suits[r] = par_suits[r - 1];
6322
/* Do the iteration as before but now in the order of the sorted denominations. */
6324
for (m=0; m<=4; m++) {
6325
j=par_suits[m].suit;
6326
tt=par_suits[m].tricks;
6328
if ((tt > par_tricks[i]) || ((tt == par_tricks[i]) &&
6329
(j < par_denom[i]))) {
6330
/* Can bid higher and make contract.*/
6331
score=rawscore(j, tt, isvul);
6334
/* Bidding higher in this denomination will not beat previous denomination
6335
and may be a sacrifice. */
6336
ut=prev_par_tricks - tt;
6337
if (j >= prev_par_denom) {
6338
/* Sacrifices higher than 7N are not permitted (but long ago
6339
the official rules did not prohibit bidding higher than 7N!) */
6340
if (prev_par_tricks == 13)
6342
/* It will be necessary to bid one level higher, resulting in
6343
one more undertrick. */
6346
/* Not a sacrifice (due to par_tricks > prev_par_tricks) */
6349
/* Compute sacrifice.*/
6350
score=rawscore(-1, ut, isvul);
6352
if (current_side == 1)
6355
if (((current_side == 0)&&(score > par_score[i])) ||
6356
((current_side == 1)&&(score < par_score[i]))) {
6358
par_score[i] = score;
6361
if (((current_side == 0)&&(score > 0)) ||
6362
((current_side == 1)&&(score < 0))) {
6363
/* New par score from a making contract.
6364
Can immediately update since score at same level in higher
6365
ranking suit is always >= score in lower ranking suit and
6366
better than any sacrifice. */
6371
par_tricks[i] = tt + ut;
6377
if (!new_score_flag && both_sides_once_flag)
6379
both_sides_once_flag = 1;
6380
current_side = 1 - current_side;
6384
presp->parScore[0][0]='N';
6385
presp->parScore[0][1]='S';
6386
presp->parScore[0][2]=' ';
6387
presp->parScore[0][3]='\0';
6388
presp->parScore[1][0]='E';
6389
presp->parScore[1][1]='W';
6390
presp->parScore[1][2]=' ';
6391
presp->parScore[1][3]='\0';
6393
itoa(par_score[0], temp, 10);
6394
strcat(presp->parScore[0], temp);
6395
itoa(par_score[1], temp, 10);
6396
strcat(presp->parScore[1], temp);
6398
for (i=0; i<=1; i++) {
6399
presp->parContractsString[0][0]='N';
6400
presp->parContractsString[0][1]='S';
6401
presp->parContractsString[0][2]=':';
6402
presp->parContractsString[0][3]='\0';
6403
presp->parContractsString[1][0]='E';
6404
presp->parContractsString[1][1]='W';
6405
presp->parContractsString[1][2]=':';
6406
presp->parContractsString[1][3]='\0';
6409
if (par_score[0] == 0) {
6410
/* Neither side can make anything.*/
6415
for (i=0; i<=1; i++) {
6417
if ( par_sacut[i] > 0 ) {
6419
dr = (par_score[i] > 0) ? 0 : 1;
6421
for (j=par_denom[i]; j<=4; j++) {
6423
t1 = ((dr+i) % 2 ) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1];
6424
t2 = ((dr+i) % 2 ) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3];
6425
tt = (t1 > t2) ? t1 : t2;
6428
for (m=4; m>=0; m--) {
6429
t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1];
6430
t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3];
6431
tu = (t3 > t4) ? t3 : t4;
6439
if (((par_tricks[i] - par_sacut[i]) != tt)||((par_denom[i] < denom_max)&&(j > denom_max)))
6442
/* Continue if the par denomination is lower than the denomination of the opponent's highest
6443
trick number and the current denomination is larger than the denomination of the opponent's
6444
highest trick number. */
6446
IniSidesString(dr, i, t1, t2, buff);
6448
if (presp->parContractsString[i][3]!='\0')
6449
strcat(presp->parContractsString[i], contr_sep);
6451
strcat(presp->parContractsString[i], buff);
6453
itoa(par_tricks[i]-6, temp, 10);
6454
buff[0]=cardSuit[denom_conv[j]];
6458
strcat(presp->parContractsString[i], temp);
6464
/* Par contract is a makeable contract.*/
6465
dr = (par_score[i] < 0) ? 0 : 1;
6467
/* If spades or diamonds, lower major / minor may also be a par contract.*/
6468
ke = (par_denom[i] == 1 || par_denom[i] == 3) ? 1 : 0;
6470
for (j=par_denom[i]; j<=par_denom[i]+ke; j++) {
6471
t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1];
6472
t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3];
6473
tt = (t1 > t2) ? t1 : t2;
6475
if (tt < par_tricks[i]) { continue; }
6477
IniSidesString(dr, i, t1, t2, buff);
6480
for (m=0; m<=4; m++) {
6481
t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1];
6482
t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3];
6483
tu = (t3 > t4) ? t3 : t4;
6486
denom_max=m; /* Lowest denomination if several denominations have max tricks. */
6490
if (presp->parContractsString[i][3]!='\0')
6491
strcat(presp->parContractsString[i], contr_sep);
6493
strcat(presp->parContractsString[i], buff);
6495
if (denom_max < par_denom[i])
6496
max_lower = par_tricks[i] - tu_max - 2;
6498
max_lower = par_tricks[i] - tu_max - 1;
6500
/* max_lower is the maximal contract lowering, otherwise opponent contract is
6501
higher. It is already known that par_score is high enough to make
6502
opponent sacrifices futile.
6503
To find the actual contract lowering allowed, it must be checked that the
6504
lowered contract still gets the score bonus points that is present in par score.*/
6506
while (max_lower > 0) {
6507
if (denom_max < par_denom[i])
6508
sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max, isvul);
6510
sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max + 1, isvul);
6511
/* Score for undertricks needed to beat the tentative lower par contract.*/
6512
sc2 = rawscore(par_denom[i], par_tricks[i] - max_lower, isvul);
6513
/* Score for making the tentative lower par contract. */
6518
/* Tentative lower par contract must be 1 trick higher, since the cost
6519
for the sacrifice is too small. */
6522
switch (par_denom[i]) {
6523
case 0: k = 0; break;
6524
case 1: case 2: k = 1; break;
6525
case 3: case 4: k = 2;
6528
max_lower = Min(max_low[k][par_tricks[i]-6], max_lower);
6530
n = CalcMultiContracts(max_lower, par_tricks[i]);
6533
buff[0]=cardSuit[denom_conv[j]];
6536
strcat(presp->parContractsString[i], temp);
6542
/* Deal with special case of 3N/5m (+400/600) */
6543
if ((par_denom[i] == 0) && (par_tricks[i] == 9)) {
6545
for (j=3; j<=4; j++) {
6546
t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1];
6547
t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3];
6548
tt = (t1 > t2) ? t1 : t2;
6550
if (tt != 11) { continue; }
6552
IniSidesString(dr, i, t1, t2, buff);
6554
if (presp->parContractsString[i][3]!='\0')
6555
strcat(presp->parContractsString[i], contr_sep);
6557
strcat(presp->parContractsString[i], buff);
6560
buff[0]=cardSuit[denom_conv[j]];
6563
strcat(presp->parContractsString[i], temp);
6569
/* Deal with special case of 2S/2H (+110) which may have 3C and 3D
6570
as additional par contract(s).*/
6571
if ((par_denom[i] <=2) && (par_denom[i] != 0) && (par_tricks[i] == 8)) {
6572
/* Check if 3C and 3D make.*/
6573
for (j=3; j<=4; j++) {
6574
t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1];
6575
t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3];
6576
tt = (t1 > t2) ? t1 : t2;
6578
if (tt != 9) { continue; }
6580
IniSidesString(dr, i, t1, t2, buff);
6584
for (m=4; m>=0; m--) {
6585
t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1];
6586
t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3];
6587
tu = (t3 > t4) ? t3 : t4;
6594
if (presp->parContractsString[i][3]!='\0')
6595
strcat(presp->parContractsString[i], contr_sep);
6597
strcat(presp->parContractsString[i], buff);
6599
if (denom_max < par_denom[i])
6600
max_lower = 9 - tu_max - 2;
6602
max_lower = 9 - tu_max - 1;
6604
/* max_lower is the maximal contract lowering, otherwise opponent contract is
6605
higher. It is already known that par_score is high enough to make
6606
opponent sacrifices futile.
6607
To find the actual contract lowering allowed, it must be checked that the
6608
lowered contract still gets the score bonus points that is present in par score.*/
6610
while (max_lower > 0) {
6611
if (denom_max < par_denom[i])
6612
sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max, isvul);
6614
sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max + 1, isvul);
6615
/* Score for undertricks needed to beat the tentative lower par contract.*/
6616
sc2 = rawscore(par_denom[i], par_tricks[i] - max_lower, isvul);
6617
/* Score for making the tentative lower par contract. */
6622
/* Tentative lower par contract must be 1 trick higher, since the cost
6623
for the sacrifice is too small. */
6626
switch (par_denom[i]) {
6627
case 0: k = 0; break;
6628
case 1: case 2: k = 1; break;
6629
case 3: case 4: k = 2;
6632
max_lower = Min(max_low[k][3], max_lower);
6634
n = CalcMultiContracts(max_lower, 9);
6637
buff[0]=cardSuit[denom_conv[j]];
6640
strcat(presp->parContractsString[i], temp);
6645
/* Deal with special case 1NT (+90) which may have 2C or 2D as additonal par
6647
if ((par_denom[i] == 0) && (par_tricks[i] == 7)) {
6648
for (j=3; j<=4; j++) {
6649
t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1];
6650
t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3];
6651
tt = (t1 > t2) ? t1 : t2;
6653
if (tt != 8) { continue; }
6655
IniSidesString(dr, i, t1, t2, buff);
6658
for (m=4; m>=0; m--) {
6659
t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1];
6660
t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3];
6661
tu = (t3 > t4) ? t3 : t4;
6668
if (presp->parContractsString[i][3]!='\0')
6669
strcat(presp->parContractsString[i], contr_sep);
6671
strcat(presp->parContractsString[i], buff);
6673
if (denom_max < par_denom[i])
6674
max_lower = 8 - tu_max - 2;
6676
max_lower = 8 - tu_max - 1;
6678
/* max_lower is the maximal contract lowering, otherwise opponent contract is
6679
higher. It is already known that par_score is high enough to make
6680
opponent sacrifices futile.
6681
To find the actual contract lowering allowed, it must be checked that the
6682
lowered contract still gets the score bonus points that is present in par score.*/
6684
while (max_lower > 0) {
6685
if (denom_max < par_denom[i])
6686
sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max, isvul);
6688
sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max + 1, isvul);
6689
/* Score for undertricks needed to beat the tentative lower par contract.*/
6690
sc2 = rawscore(par_denom[i], par_tricks[i] - max_lower, isvul);
6691
/* Score for making the tentative lower par contract. */
6696
/* Tentative lower par contract must be 1 trick higher, since the cost
6697
for the sacrifice is too small. */
6700
switch (par_denom[i]) {
6701
case 0: k = 0; break;
6702
case 1: case 2: k = 1; break;
6703
case 3: case 4: k = 2;
6706
max_lower = Min(max_low[k][3], max_lower);
6708
n = CalcMultiContracts(max_lower, 8);
6711
buff[0]=cardSuit[denom_conv[j]];
6714
strcat(presp->parContractsString[i], temp);
6726
int rawscore(int denom, int tricks, int isvul) {
6727
int game_bonus, level, score;
6729
/* Computes score for undoubled contract or a doubled contract with
6730
for a given number of undertricks. These are the only possibilities
6731
for a par contract (aside from a passed out hand).
6733
denom - 0 = NT, 1 = Spades, 2 = Hearts, 3 = Diamonds, 4 = Clubs
6734
(same order as results from double dummy solver); -1 undertricks
6735
tricks - For making contracts (7-13); otherwise, number of undertricks.
6736
isvul - True if vulnerable */
6740
return -300 * tricks + 100;
6742
return -200 * tricks + 100;
6743
return -300 * tricks + 400;
6749
score=10 + 30 * level;
6753
else if ((denom==1)||(denom==2)) {
6764
score+= (isvul ? 500 : 300);
6770
score+= (isvul ? 750 : 500);
6772
else if (level==7) {
6773
score+= (isvul ? 1500 : 1000);
6781
void IniSidesString(int dr, int i, int t1, int t2, char stri[]) {
6823
int CalcMultiContracts(int max_lower, int tricks) {
6827
case 5: if (max_lower==3) {n = 2345;}
6828
else if (max_lower==2) {n = 345;}
6829
else if (max_lower==1) {n = 45;}
6832
case 4: if (max_lower==3) {n = 1234;}
6833
else if (max_lower==2) {n = 234;}
6834
else if (max_lower==1) {n = 34;}
6837
case 3: if (max_lower==2) {n = 123;}
6838
else if (max_lower==1) {n = 23;}
6841
case 2: if (max_lower==1) {n = 12;}
6844
default: n = tricks-6;