From: H.G. Muller Date: Fri, 27 Sep 2013 12:04:53 +0000 (+0200) Subject: Version 0.12: King safety and Kylin terms, PV cuts X-Git-Tag: 0.18~28 X-Git-Url: http://winboard.nl/cgi-bin?p=hachu.git;a=commitdiff_plain;h=44fcfc3374cbb7824b6b2a5318bea14919af5ac9 Version 0.12: King safety and Kylin terms, PV cuts Add an option to prevent PV cuts in analysis mode. Add terms for calculating King Safety and Kylin promotion danger, but do not activate them yet. --- diff --git a/hachu.c b/hachu.c index 9adacca..0b2541c 100644 --- a/hachu.c +++ b/hachu.c @@ -11,15 +11,16 @@ // promotions by pieces with Lion power stepping in & out the zone in same turn // promotion on capture -#define VERSION "0.11 kill" +#define VERSION "0.12n" #define PATH level==0 || path[0] == 0x848f1 && (level==1 /*|| path[1] == 0x3f081 && (level == 2 || path[2] == 0x6f0ac && (level == 3 || path[3] == 0x3e865 && (level == 4 || path[4] == 0x4b865 && (level == 5))))*/) //define PATH 0 #define HASH #define KILLERS -#define XNULLMOVE +#define NULLMOVE #define LIONTRAP +#define XKINGSAFETY #include #include @@ -131,8 +132,8 @@ typedef struct { char fireMask; } UndoInfo; -char *array, fenArray[4000], *reason; -int bWidth, bHeight, bsize, zone, currentVariant, chuFlag, tenFlag, chessFlag, repDraws, tsume; +char *array, fenArray[4000], startPos[4000], *reason; +int bWidth, bHeight, bsize, zone, currentVariant, chuFlag, tenFlag, chessFlag, repDraws, tsume, pvCuts; int stm, xstm, hashKeyH=1, hashKeyL=1, framePtr, msp, nonCapts, rootEval, filling, promoDelta; int retMSP, retFirst, retDep, pvPtr, level, cnt50, mobilityScore; int nodes, startTime, lastRootMove, lastRootIter, tlim1, tlim2, tlim3, repCnt, comp, abortFlag; @@ -544,7 +545,7 @@ typedef struct { char bulk; } PieceInfo; // piece-list entry -int last[2], royal[2]; +int last[2], royal[2], kylin[2]; PieceInfo p[NPIECES]; // piece list typedef struct { @@ -562,6 +563,7 @@ typedef struct { int ponder; int randomize; int postThinking; + int noCut=1; // engine-defined option int resign; // engine-defined option int contemptFactor; // likewise int seed; @@ -574,7 +576,7 @@ int attackMaps[200*BSIZE], *attacks = attackMaps; char distance[2*BSIZE]; // distance table char promoBoard[BSIZE]; // flags to indicate promotion zones char rawFire[BSIZE+2*BWMAX]; // flags to indicate squares controlled by Fire Demons -signed char PST[3*BSIZE]; +signed char PST[4*BSIZE]; #define board (rawBoard + 6*BHMAX + 3) #define fireBoard (rawFire + BWMAX + 1) @@ -622,6 +624,7 @@ SqueezeOut (int n) for(i=n; ibulk; p[i].mobWeight = v > 600 ? 0 : v >= 400 ? 1 : v >= 300 ? 2 : v > 150 ? 3 : v >= 100 ? 2 : 0; -// if(Lance(list->range)) p[i].mobWeight = 5, p[i].pst = 0; // clear path but don't move forward + if(Lance(list->range),0) + p[i].mobWeight = 5 + 3*(list->range[4]==X), p[i].pst = 0; // clear path but don't move forward for(j=stm+2; j<= last[stm]; j+=2) { if(p[j].promo >= i) p[j].promo += 2; } if(royal[stm] >= i) royal[stm] += 2; + if(kylin[stm] >= i) kylin[stm] += 2; if(p[i].value == (currentVariant == V_SHO ? 410 : 280) ) royal[stm] = i, p[i].pst = 0; p[i].qval = (currentVariant == V_TENJIKU ? list->ranking : 0); // jump-capture hierarchy return i; @@ -801,6 +805,7 @@ SetUp(char *array, int var) p[n].promoFlag &= n&1 ? P_WHITE : P_BLACK; p[m].promo = -1; p[m].pos = ABSENT; + if(p[m].value == 10*LVAL) kylin[color] = n; // remember piece that promotes to Lion } else p[n].promo = -1; // unpromotable piece //printf("piece = %c%-2s %d(%d) %d/%d\n", color ? 'w' : 'b', name, n, m, last[color], last[!color]); } @@ -818,18 +823,20 @@ SetUp(char *array, int var) } for(i=0; i 0) + if((j = p[i].promo) > 0 && p[i].promoGain) p[i].promoGain = (p[j].value - p[i].value - 30)*1.25, p[i].value = p[j].value - 30; else p[i].promoGain = 0; + if(j > 0 && p[i].pst == BH) p[i].pst = 3*BW*BH; // use white pre-prom bonus board[p[i].pos] = i; rootEval += p[i].value + PST[p[i].pst + p[i].pos]; promoDelta += p[i].promoGain; filling += p[i].bulk; } else p[i].promoGain = 0; for(i=BLACK+2; i<=last[BLACK]; i+=2) if(p[i].pos != ABSENT) { - if(p[i].promoGain && (j = p[i].promo) > 0) + if((j = p[i].promo) > 0 && p[i].promoGain) p[i].promoGain = (p[j].value - p[i].value - 30)*1.25, p[i].value = p[j].value - 30; else p[i].promoGain = 0; + if(j > 0 && p[i].pst == BH) p[i].pst = 3*BW*BH + BH; // use black pre-prom bonus board[p[i].pos] = i; rootEval -= p[i].value + PST[p[i].pst + p[i].pos]; promoDelta -= p[i].promoGain; @@ -910,14 +917,19 @@ Init (int var) } // piece-square tables - for(i=0; i BH-4 ? (i < 3 ? 5 : i == 3 ? 2 : i == 4 ? 1 : 0) : 0; + PST[2*BH*BW+BH+s] = ((BH-1)*(BH-1) - (2*i - BH + 1)*(2*i - BH + 1) - (2*j - BH + 1)*(2*j - BH + 1))/6; + PST[3*BH*BW+s] = PST[3*BH*BW+BH+s] = PST[BH+s]; // as stepper, but with pre-promotion bonus W/B + } + if(zone > 1) PST[3*BW*BH+BW*(BH-1-zone) + j] += 10, PST[3*BW*BH+BH + BW*zone + j] += 10; } p[EDGE].qval = 5; // tenjiku jump-capturer sentinel @@ -1653,7 +1665,7 @@ GenCapts(int sqr, int victimValue) int Evaluate (int difEval) { - int wLion, bLion, score=mobilityScore; + int wLion, bLion, wKing, bKing, score=mobilityScore; #ifdef LIONTRAP #define lionTrap (PST + 2*BH*BW) @@ -1666,6 +1678,25 @@ Evaluate (int difEval) } #endif +#ifdef KINGSAFETY + // basic centralization in end-game (also facilitates bare-King mating) + wKing = p[royal[WHITE]].pos; if(wKing == ABSENT) wKing = p[royal[WHITE]+1].pos; + bKing = p[royal[BLACK]].pos; if(bKing == ABSENT) bKing = p[royal[BLACK]+1].pos; + if(filling < 32) { + score += (PST[3*BW*BH+wKing] - PST[3*BW*BH+bKing])*(32 - filling) >> 4; + } +#endif + +#ifdef KYLIN + // bonus for having Kylin in late end-game, where it could promote to Lion + if((filling < 64) { + if((wLion = kylin[WHITE]) && p[wLion].pos != ABSENT) + score += (64 - filling)*kylinProm[wLion]; + if((filling < 64 && (bLion = kylin[BLACK]) && p[bLion].pos != ABSENT) + score -= (64 - filling)*kylinProm[bLion]; + } +#endif + return difEval - (filling*filling*promoDelta >> 16) + (stm ? score : -score); } @@ -1731,7 +1762,8 @@ if(PATH) /*pboard(board),pmap(attacks, BLACK),*/printf("search(%d) {%d,%d} eval= iterDep = -(depth == 0); tb.fireMask = phase = 0; #ifdef HASH - index = (hashKeyL ^ 327*stm ^ oldPromo*(63121 + promoSuppress)) & hashMask; + index = hashKeyL ^ 327*stm ^ (oldPromo + 987981)*(63121 + promoSuppress); + index = index + (index >> 16) & hashMask; nr = (hashKeyL >> 30) & 3; hit = -1; if(hashTable[index].lock[nr] == hashKeyH) hit = nr; else if(hashTable[index].lock[4] == hashKeyH) hit = 4; @@ -1743,9 +1775,12 @@ if(PATH) printf("# probe hash index=%x hit=%d\n", index, hit),fflush(stdout); (bestScore >= beta || hashTable[index].flag[hit] & H_UPPER) ) { iterDep = resDep = hashTable[index].depth[hit]; bestMoveNr = 0; if(!level) iterDep = 0; // no hash cutoff in root + if(pvCuts && iterDep >= depth && hashMove && bestScore < beta && bestScore > alpha) + iterDep = depth - 1; // prevent hash cut in PV node } } else { // decide on replacement - if(depth >= hashTable[index].depth[nr]) hit = nr; else hit = 4; + if(depth >= hashTable[index].depth[nr] || + depth+1 == hashTable[index].depth[nr] && !(nodes&3)) hit = nr; else hit = 4; hashMove = 0; } if(PATH) printf("# iterDep = %d score = %d move = %s\n",iterDep,bestScore,MoveToText(hashMove,0)),fflush(stdout); @@ -1778,7 +1813,7 @@ if(PATH)printf("new moves, phase=%d\n", phase); int nullDep = depth - 3; stm ^= WHITE; score = -Search(-beta, 1-beta, -difEval, nullDep= beta) { msp = oldMSP; retDep += 3; return score + (score < curEval); } } #endif @@ -2027,7 +2062,7 @@ pplist() { int i, j; for(i=0; i<182; i++) { - printf("%3d. %3d %3d %4d %02x %d %x %3d ", i, p[i].value, p[i].promo, p[i].pos, p[i].promoFlag&255, p[i].qval, p[i].bulk, p[i].promoGain); + printf("%3d. %3d %3d %4d %02x %d %d %x %3d ", i, p[i].value, p[i].promo, p[i].pos, p[i].promoFlag&255, p[i].mobWeight, p[i].qval, p[i].bulk, p[i].promoGain); for(j=0; j<8; j++) printf(" %2d", p[i].range[j]); if(i<2 || i>11) printf("\n"); else printf(" %02x\n", fireFlags[i-2]&255); } @@ -2191,6 +2226,7 @@ Setup2 (char *fen) } rootEval = promoDelta = filling = cnt50 = moveNr = 0; SetUp(array, currentVariant); + strcpy(startPos, array); sup0 = sup1 = sup2 = ABSENT; hashKeyH = hashKeyL = 87620895*currentVariant; return stm; @@ -2410,7 +2446,7 @@ printf("# ponder=%s\n", MoveToText(pv[1],0)); int TakeBack(int n) { // reset the game and then replay it to the desired point int last, stm; - Init(currentVariant); stm = Setup2(NULL); + Init(currentVariant); stm = Setup2(startPos); printf("# setup done");fflush(stdout); last = moveNr - n; if(last < 0) last = 0; for(moveNr=0; moveNr