X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=hachu.c;h=40c31e5a285e23a41593ad89444f2c68a3417b02;hb=5c1fa8b0d0076c229f483e7c868bdaa6f1103389;hp=c59149b3591ce37ea9a621721e62e6263393f885;hpb=5f159ca2bec501050e3f234c802f1e8e51b937c6;p=hachu.git diff --git a/hachu.c b/hachu.c index c59149b..40c31e5 100644 --- a/hachu.c +++ b/hachu.c @@ -8,11 +8,10 @@ // TODO: // in GenCapts we do not generate jumps of more than two squares yet -// Chu rules for Lion capture // promotions by pieces with Lion power stepping in & out the zone in same turn // promotion on capture -#define VERSION 0.0 +#define VERSION "0.1beta" //define PATH level==0 || level==1 && path[0] == 0x55893 #define PATH 0 @@ -34,10 +33,12 @@ } #endif -#define BW 24 -#define BH 12 -#define BSIZE BW*BH*2 -#define ZONE 4 +#define BW bWidth +#define BH bHeight +#define BHMAX 15 +#define BWMAX (2*BHMAX) +#define BSIZE BWMAX*BHMAX +#define ZONE zone #define ONE 0 @@ -85,13 +86,14 @@ typedef struct { int from, to, piece, victim, new, booty, epSquare, epVictim, ep2Square, ep2Victim, revMoveCount, savKeyL, savKeyH; } UndoInfo; +int bWidth, bHeight, bsize, zone, currentVariant; int stm, xstm, hashKeyH, hashKeyL, framePtr, msp, nonCapts, rootEval, retMSP, retFirst, pvPtr, level, cnt50, chuFlag=1; int nodes, startTime, tlim1, tlim2; Move retMove, moveStack[10000], path[100], repStack[300], pv[1000]; #define X 36 /* slider */ -#define J -1 /* jump */ -#define N -2 /* Knight */ +#define N -1 /* Knight */ +#define J -2 /* jump */ #define D -3 /* linear double move */ #define T -4 /* linear triple move */ #define L -5 /* true Lion move */ @@ -268,7 +270,7 @@ char daiArray[] = "LN:STICSGKGSCI:STNL/:RV.:CS.:FL.:BT:DE:BT.:FL.:CS.:RV/.:VO.:A "r:fd:sm:vmb:dh:dk:fk:dk:dhb:vm:sm:fdr/.:vo.:ab.:ew:ph:ln:kn:ew.:ab.:vo./:rv.:cs.:fl.:bt:de:bt.:fl.:cs.:rv/ln:sticsgkgsci:stnl"; typedef struct { - int boardWidth, boardFiles, zoneDepth, boardRanks; // board sizes + int boardWidth, boardFiles, boardRanks, zoneDepth; // board sizes char *name; // WinBoard name char *array; // initial position } VariantDesc; @@ -418,24 +420,37 @@ typedef struct { int squareKey[BSIZE]; -int rawBoard[BSIZE + 11*BW + 6]; +int rawBoard[BSIZE + 11*BHMAX + 6]; //int attacks[2*BSIZE]; // attack map int attackMaps[200*BSIZE], *attacks = attackMaps; char distance[2*BSIZE]; // distance table char promoBoard[BSIZE]; signed char PST[2*BSIZE]; -#define board (rawBoard + 6*BW + 3) +#define board (rawBoard + 6*BHMAX + 3) #define dist (distance + BSIZE) PieceDesc * -LookUp (char *name, PieceDesc *list) +ListLookUp (char *name, PieceDesc *list) { // find piece of given name in list of descriptors int i=0; while(list->name && strcmp(name, list->name)) i++, list++; return (list->name == NULL ? NULL : list); } +PieceDesc * +LookUp (char *name, int var) +{ // search piece of given name in all lists relevant for given variant + PieceDesc *desc; + switch(var) { + case 1: // Dai + desc = ListLookUp(name, daiPieces); + if(desc) return desc; + case 0: // Chu + return ListLookUp(name, chuPieces); + } +} + void SqueezeOut (int n) { // remove piece number n from the mentioned side's piece list (and adapt the reference to the displaced pieces!) @@ -528,8 +543,8 @@ AddPiece (int stm, PieceDesc *list) for(j=0; j<8; j++) p[i].range[j] = list->range[j^4*(WHITE-stm)]; switch(Range(p[i].range)) { case 1: p[i].pst = BH; break; - case 2: p[i].pst = BSIZE; break; - default: p[i].pst = BSIZE + BH; break; + case 2: p[i].pst = bsize; break; + default: p[i].pst = bsize + BH; break; } key = (stm == WHITE ? &list->whiteKey : &list->blackKey); if(!*key) *key = ~(myRandom()*myRandom()); @@ -544,7 +559,7 @@ AddPiece (int stm, PieceDesc *list) } void -SetUp(char *array, PieceDesc *list) +SetUp(char *array, int var) { int i, j, n, m, nr, color; char c, *q, name[3]; @@ -564,11 +579,11 @@ SetUp(char *array, PieceDesc *list) name[0] += 'A' - 'a'; if(name[1]) name[1] += 'A' - 'a'; } else color = WHITE; - p1 = LookUp(name, list); + p1 = LookUp(name, var); n = AddPiece(color, p1); p[n].pos = j; if(p1->promoted[0]) { - p2 = LookUp(p1->promoted, list); + p2 = LookUp(p1->promoted, var); m = AddPiece(color, p2); if(m <= n) n += 2; p[n].promo = m; @@ -595,10 +610,17 @@ int myRandom() } void -Init() +Init (int var) { int i, j, k; + currentVariant = var; + bWidth = variants[var].boardWidth; + bHeight = variants[var].boardRanks; + zone = variants[var].zoneDepth; + bsize = bWidth*bHeight; + chuFlag = (var == 0); + for(i= -1; i<9; i++) { // board steps in linear coordinates kStep[i] = STEP(direction[i&7].x, direction[i&7].y); // King nStep[i] = STEP(direction[(i&7)+8].x, direction[(i&7)+8].y); // Knight @@ -620,7 +642,7 @@ Init() } // fill distance table - for(i=0; i= S) { // in any case, do a jump of 2 NewNonCapture(x, x + 2*v, pFlag); - if(r < N) { // Lion power, also single step + if(r < J) { // Lion power, also single step if(!NewNonCapture(x, x + v, pFlag)) nullMove = x; if(r == L) { // true Lion, also Knight jump v = nStep[j]; @@ -806,6 +831,11 @@ MapOneColor (int start, int last, int *map) for(j=0; j<8; j++) { int x = p[i].pos, v = kStep[j], r = p[i].range[j]; if(r < 0) { // jumping piece, special treatment + if(r == N) { + x += nStep[j]; + if(board[x] != EMPTY && board[x] != EDGE) + map[2*x + start] += one[8]; + } else if(r >= S) { // in any case, do a jump of 2 if(board[x + 2*v] != EMPTY && board[x + 2*v] != EDGE) map[2*(x + 2*v) + start] += one[j]; @@ -850,15 +880,15 @@ void MapFromScratch (int *map) { int i; - for(i=0; i<2*BSIZE; i++) map[i] = 0; + for(i=0; i<2*bsize; i++) map[i] = 0; MapOneColor(0, last[BLACK], map); MapOneColor(1, last[WHITE], map); } void Connect (int sqr, int piece, int dir) -{ - int x, step = kStep[dir], r1 = p[piece].range[dir], r2 = p[piece].range[dir+1], piece1, piece2; +{ // scan to both sides along ray to elongate attacks from there, and remove our own attacks on there, if needed + int x, step = kStep[dir], r1 = p[piece].range[dir], r2 = p[piece].range[dir+4], piece1, piece2; int d1, d2, r, y, c; if((attacks[2*sqr] + attacks[2*sqr+1]) & attackMask[dir]) { // there are incoming attack(s) from 'behind' @@ -877,15 +907,17 @@ Connect (int sqr, int piece, int dir) attacks[2*y + (piece1 & WHITE)] += one[dir]; // count attack UPDATE_MOBILITY(piece1, d2); } else UPDATE_MOBILITY(piece1, r1 - d1); // does not connect, but could still gain mobility - if(d1 + d2 <= (r2 = p[piece2].range[dir])) { // 2 hits 1 + if(d1 + d2 <= (r2 = p[piece2].range[dir+4])) { // 2 hits 1 attacks[2*x + (piece2 & WHITE)] += one[dir+4]; // count attack UPDATE_MOBILITY(piece2, d1); } else UPDATE_MOBILITY(piece2, r2 - d2); // does not connect, but could still gain mobility + // if r1 or r2<0, moves typically jump, and thus cannot be unblocked. Exceptions are FF and BS distant moves. + // test for d1+d2 > 2 && rN == F && d== 3 or rN == S } else { // we were only attacked from behind r = (r2 = p[piece1].range[dir]) - d1; - if(r < 0 || c > one[dir+1]) { // Oops! This was not our attacker, or not the only one. There must be a jump attack from even further behind! + if(r < 0 || c > one[dir+4]) { // Oops! This was not our attacker, or not the only one. There must be a jump attack from even further behind! // for now, forget jumpers } y = sqr; @@ -901,7 +933,7 @@ Connect (int sqr, int piece, int dir) } // we hit nothing with the extended move of the attacker behind us. UPDATE_MOBILITY(piece1, r2 - d1); - r = r1 - r2; // extra squares covered by mover + r = r1 - r2 + d1; // extra squares covered by mover while(r-- > 0) if(board[y+=step] != EMPTY) { d2 = dist[y-sqr]; piece2 = board[y]; @@ -911,6 +943,7 @@ Connect (int sqr, int piece, int dir) return; } } + // if r2<0 we should again test for F and S moves } else // no incoming attack from behind if(c = (attacks[2*sqr] + attacks[2*sqr+1]) & attackMask[dir+4]) { // but incoming attack(s) from 'ahead' @@ -935,7 +968,7 @@ Connect (int sqr, int piece, int dir) } // we hit nothing with the extended move of the attacker behind us. UPDATE_MOBILITY(piece2, r2 - d1); - r = r2 - r1; // extra squares covered by mover + r = r2 - r1 + d2; // extra squares covered by mover while(r-- > 0) if(board[x-=step] != EMPTY) { d1 = dist[x-sqr]; piece1 = board[x]; @@ -964,25 +997,64 @@ Connect (int sqr, int piece, int dir) } } +inline int +Hit (int r, int d) +{ // test if move with range r reaches over (un-obstructed) distance d + if(r < 0) switch(r) { + case J: return (d == 2); + case D: + case L: return (d <= 2); + case T: + case F: return (d <= 3); + case S: return 1; + default: return 0; + } else return (d <= r); + return 0; // not reached +} + void -Disconnect (int sqr, int dir) +Disconnect (int sqr, int piece, int dir) { - int x = sqr, step = kStep[dir], piece1, piece2, y; + int x = sqr, step = kStep[dir], piece1, piece2, d1, d2, r1, r2, y; while( board[x+=step] == EMPTY ); - if(board[x] != EDGE) { // x has hit a piece - piece1 = board[x]; + piece1 = board[x]; + if(piece1 != EDGE) { // x has hit a piece + d1 = dist[x-sqr]; + r1 = p[piece1].range[dir+4]; y = sqr; while( board[y-=step] == EMPTY ); - if(board[y] != EDGE) { // both ends of the ray hit a piece - piece2 = board[y]; - + piece2 = board[y]; + if(piece2 != EDGE) { // both ends of the ray hit a piece + d2 = dist[y-sqr]; + r2 = p[piece2].range[dir]; + if(r1 >= d1) { // piece1 hits us + attacks[2*sqr + (piece1 & WHITE)] += one[dir+4]; + if(r1 >= d1 + d2) // was hitting piece2 before, now blocked + attacks[2*y + (piece1 & WHITE)] -= one[dir+4]; + } + if(r2 >= d2) { // piece2 hits us + attacks[2*sqr + (piece2 & WHITE)] += one[dir]; + if(r2 >= d1 + d2) // was hitting piece1 before, now blocked + attacks[2*x + (piece2 & WHITE)] -= one[dir]; + } + if( Hit(p[piece].range[dir], d1) ) + attacks[2*sqr + stm] += one[dir]; + if( Hit(p[piece].range[dir+4], d2) ) + attacks[2*sqr + stm] += one[dir+4]; return; } } else { x = sqr; while( board[x-=step] == EMPTY ); - if(board[x] == EDGE) return; // ray empty on both sides + piece1 = board[x]; + if(piece1 == EDGE) return; // ray empty on both sides + d1 = dist[x-sqr]; + r1 = p[piece1].range[dir]; + dir += 4; } - // we only get here if one side hits a - + // we only get here if one side looks to the board edge + if(r1 >= d1) // piece1 hits us + attacks[2*sqr + (piece1 & WHITE)] += one[dir^4]; + if( Hit(p[piece].range[dir], d1) ) + attacks[2*sqr + stm] += one[dir]; } void @@ -990,7 +1062,7 @@ Occupy (int sqr) { // determines attacks on square and blocking when a piece lands on an empty square int i; for(i=0; i<4; i++) { - Disconnect(sqr, i); + Disconnect(sqr, board[sqr], i); } } @@ -1332,7 +1404,7 @@ if(flag & depth >= 0) printf("%2d:%d found %d/%d\n", depth, iterDep, curMove, ms repStack[level+200] = hashKeyH; path[level++] = move; -attacks += 2*BSIZE; +attacks += 2*bsize; MapFromScratch(attacks); // for as long as incremental update does not work. if(PATH) pmap(attacks, stm); if(chuFlag && p[tb.victim].value == 1000) { // verify legality of Lion capture in Chu Shogi @@ -1352,7 +1424,7 @@ if(PATH) pmap(attacks, stm); score = 0; #endif abortMove: -attacks -= 2*BSIZE; +attacks -= 2*bsize; level--; repetition: UnMake(&tb); @@ -1535,7 +1607,7 @@ UnMake2 (MOVE move) int Setup2 (char *fen) { - SetUp(chuArray, chuPieces); + SetUp(variants[currentVariant].array, currentVariant); sup0 = sup1 = sup2 = ABSENT; rootEval = cnt50 = hashKeyH = hashKeyL = 0; return WHITE; @@ -1634,7 +1706,7 @@ Highlight(char *coords) { int i, j, n, sqr, cnt=0; char b[BSIZE], buf[2000], *q; - for(i=0; i