From: H.G.Muller Date: Wed, 28 Dec 2016 19:39:23 +0000 (+0100) Subject: Implement drop restrictions for Shogi X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=28d783196871ee16b9e4cb7ee18ee2fee058ff74;p=crazywa.git Implement drop restrictions for Shogi The various routines for dropping pieces now repect the rules that pieces should not be dropped where they have no moves. --- diff --git a/dropper.c b/dropper.c index d755acf..8087bf5 100644 --- a/dropper.c +++ b/dropper.c @@ -58,7 +58,7 @@ int moveNr; // part of game state; incremented by MakeMove #define promoGain (rawGain + 1) int pvStack[MAXPLY*MAXPLY/2]; -int nrRanks, nrFiles, specials, pinCodes, maxDrop, moveSP, pawn, *pvPtr = pvStack, boardEnd, searchNr; +int nrRanks, nrFiles, specials, pinCodes, maxDrop, moveSP, pawn, lanceMask, *pvPtr = pvStack, boardEnd, perpLoses, searchNr; int rawInts[21*22], pieceValues[96], pieceCode[96]; signed char rawChar[32*22], steps[512]; unsigned char rawByte[91*22], firstDir[64], rawBulk[98], handSlot[97], promoCode[96], aVal[64], vVal[64], rawLocation[96+23]; @@ -316,19 +316,20 @@ euroFEN[] = "r w", // promotion codes for unpromoted pieces. Will be ANDed with Z_WHITE or Z_BLACK to fill promoCode[] table -#define Z_FIDE 1 /* piece has promotion choice */ +#define Z_LAST 1 /* first or last rank */ #define Z_2ND 0x66 /* must promote on last 2 ranks */ #define Z_MUST 0x78 /* must promote in entire zone */ #define Z_WHITE 0x2B /* bits applying to white zone */ #define Z_BLACK 0x55 /* bits applying to black zone */ -#define Z_LAST 0x80 /* ???? */ #define Z_DOUBLE 0x80 /* where Pawns have double step */ -chessProms[16] = { Z_FIDE|Z_MUST }, +chessProms[16] = { Z_MUST }, shogiProms[16] = { Z_MUST, Z_2ND, COLOR, 0, Z_MUST, Z_MUST, Z_2ND }, toriProms[16] = { Z_MUST, 0, 0, 0, 0, Z_MUST }, waProms[16] = { Z_MUST, Z_2ND, Z_MUST, Z_MUST, Z_MUST, COLOR, COLOR, Z_MUST, Z_MUST, Z_MUST, COLOR, Z_MUST, COLOR, Z_MUST }; +int lances[] = { 1, 3, 0103, 0103, 3, 1, 1 }; // bitmap indicating piece types with drop restriction (LSB = Pawn) in various variants + char *betza[] = { // piece defs for sending to GUI NULL, // suppresses setup command "", @@ -444,6 +445,8 @@ printf("# variant %d: %s\n", v, variants[v].name); moves = variants[v].dirs; startPos= variants[v].fen; codes = variants[v].proms; + lanceMask = lances[v]; + perpLoses = v; // this works for now, as only zh allows perpetuals if((p = betza[v])) { // configure GUI for this variant printf("setup (%s) %dx%d+%d_%s %s 0 1", ptc[v], nrFiles, nrRanks, maxDrop+1, (v == 4 ? "chu" : "shogi"), startPos); @@ -773,8 +776,8 @@ MoveGen (int stm, MoveStack *m, int castle) } if(promote & stm) { // promotion is (also?) possible moveStack[--m->firstMove] = (move | from << 8 | to + 11) + (vVal[victim-WHITE] + 20 << 24); // put it amongst captures - if(promoCode[piece-WHITE] & Z_FIDE) { // only for FIDE Pawns - moveStack[--m->firstMove] = move | from << 8 | to - 11 + (stm >> 6)*44; // under-promotion + if(!perpLoses) { // only for FIDE Pawns + moveStack[--m->firstMove] = move | from << 8 | to - 11 + (stm >> 6)*44; // turn previously-generated deferral into under-promotion // other under-promotions could go here (Capahouse?) } } @@ -804,18 +807,19 @@ MoveGen (int stm, MoveStack *m, int castle) void CheckDrops (int stm, int king) { - int i; - stm ^= COLOR; - for(i=maxDrop; i>=0; i--) { - int piece = stm + i, from = handSlot[piece]; + int i, lowest = 0; + if(perpLoses) lowest = !!(pawnCount[sqr2file[king]] & maxBulk[stm]); // in Shogi no Pawn if file already crowded with those + else lowest = (stm == WHITE ? king < 2*22 : king >= 6*22); // in zh no Pawn from back rank + for(i=maxDrop; i>=lowest; i--) { + int piece = stm + i, from = handSlot[piece^COLOR]; if((signed char)board[from] < -1) { // piece type is in hand int step, dir = 2*firstDir[piece-WHITE]; while((step = steps[dir++])) { int to = king, range = steps[dir++]; - if((range & 3) == 2) break; // non-capture direction + if((range & 3) == 2) continue; // non-capture direction while(board[to-=step] == 0) { moveStack[moveSP++] = to | from << 8; - if((range -= 8) <= 0) break; + if((range -= 8) <= 0) { if(i == 0 && (to < 22 || to >= boardEnd-22)) moveSP--; break; } } } } @@ -825,12 +829,20 @@ CheckDrops (int stm, int king) void EvasionDrops (int stm, StackFrame *f) { - int i, x = f->checker, v = f->checkDir; - stm ^= COLOR; + int i, x = f->checker, v = f->checkDir, s = stm ^ COLOR; while(board[x+=v] == 0) { // all squares on check ray - i = (x < 22 || x >= 7*22); // not on last rang. *** WRONG FOR SHOGI *** - for(i=0; i<=maxDrop; i++) { // all droppable types - int piece = stm + i, from = handSlot[piece]; + int last = maxDrop; + i = zoneTab[x] & Z_LAST; // Pawn not on first & last rank (OK for zh) + if(perpLoses) { // but it is Shogi! + if(!(zoneTab[x] & stm)) i = 0; // outside zone, so dropping is always allowed + else if(perpLoses < 5) { // Shogi variant with Lance + i *= 2; // no Pawn, then also no Lance! + last += 1 - (zoneTab[x] & (Z_2ND & ~COLOR)) + (perpLoses & 4) >> 3; // on last 2 ranks trim off Knight (not in Wa) + } + if(pawnCount[sqr2file[x]] & maxBulk[stm]) i += !i; // no Pawn in pawn-crowded file + } + for(; i<=last; i++) { // all droppable types + int piece = s + i, from = handSlot[piece]; if((signed char)board[from] < -1) // piece type is in hand moveStack[moveSP++] = from << 8 | x; } @@ -840,16 +852,23 @@ EvasionDrops (int stm, StackFrame *f) void AllDrops (int stm) { - int i, start = 22, end = boardEnd-22; - stm ^= COLOR; + int i, mask = lanceMask; for(i=0; i<=maxDrop; i++) { - int piece = stm + i, from = handSlot[piece]; + int piece = stm + i, from = handSlot[piece^COLOR]; if((signed char)board[from] < -1) { // piece type is in hand - int r, f; - for(r=start; r>= 1; } } @@ -871,7 +890,7 @@ DiscoTest (int stm, int fromSqr, int king, StackFrame *f) void CheckTest (int stm, StackFrame *ff, StackFrame *f) { - if(ff->mutation == -2) f.checker = CK_NONE, f.checkDist = 0; else { // null move never checks + if(ff->mutation == -2) f->checker = CK_NONE, f->checkDist = 0; else { // null move never checks int king = location[stm+31]; // own King int vec = king - ff->toSqr; int match = captCode[vec] & pieceCode[ff->toPiece]; @@ -1357,7 +1376,7 @@ MoveToText (int move) to = toDecode[to]; if(inc > 0) promo = pieceID[inc - 16]; // move is promotion else if(castle) to = 2*to - from; // move is castling, and 'to' indicates Rook; calculate King to-square - if(promo == '+' && promoCode[WHITE] & Z_FIDE) promo = 'q'; + if(promo == '+' && !perpLoses) promo = 'q'; if(from%22 > 10) sprintf(buf, "%c@%c%d", pieces[dropType[from]-1&~COLOR], 'a'+(to%22), 1+(to/22)); // move is drop else sprintf(buf, "%c%d%c%d%c", 'a'+(from%22), 1+(from/22), 'a'+(to%22), 1+(to/22), promo); return buf; @@ -1385,6 +1404,7 @@ ParseMove(int stm, char *s) case 'n': m += in; break; case 'b': m += 2*in; break; case 'r': m += 3*in; break; + case '=': m -= 11; break; // no promotion after all } } else if(board[from] == stm + 31 && (f - f2 > 1 || f2 - f > 1)) { // castling m = 22*8+10 + (f > f2 ? 0 : 11) + 22*(r2 == 7) + (from << 8);