Implement promotion drops
authorH.G.Muller <hgm@hgm-xboard.(none)>
Tue, 10 Apr 2018 15:42:31 +0000 (17:42 +0200)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Tue, 10 Apr 2018 16:16:43 +0000 (18:16 +0200)
The various routines for generating drop moves are now also able to
generate drops of the promoted version of the piece in hand, controlled
by a variable 'promoDrops'. For now this variable is set to forbid such
drops.

dropper.c

index 9685e96..e7b834c 100644 (file)
--- a/dropper.c
+++ b/dropper.c
@@ -65,7 +65,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, queen, lanceMask, knightLim, *pvPtr = pvStack, boardEnd, perpLoses, searchNr;
+int nrRanks, nrFiles, specials, pinCodes, maxDrop, promoDrops, moveSP, pawn, queen, lanceMask, knightLim, *pvPtr = pvStack, boardEnd, perpLoses, searchNr;
 int  frontier, killZone, impasse, frontierPenalty, killPenalty;
 int rawInts[21*22], pieceValues[96], pieceCode[96];
 signed char   rawChar[32*22], steps[512];
@@ -485,6 +485,7 @@ GameInit (char *name)
     lanceMask = lances[v];
     knightLim = (v >= KNIGHTLESS) * 6; // 6 for variants where last piece can be dropped on last two ranks
     perpLoses = v; // this works for now, as only zh allows perpetuals
+    promoDrops = 0;
 
     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, (pieces == waIDs ? "chu" : "shogi"), startPos);
@@ -905,10 +906,22 @@ CheckDrops (int stm, int king)
     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--) {
+    for(i=maxDrop; i>=0; 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];
+           int step, dir;
+           if(promoDrops) { // for variants that also can drop promoted side up
+               dir = 2*firstDir[piece-WHITE+16];
+               while((step = steps[dir++])) {
+                   int to = king, range = steps[dir++];
+                   while(board[to-=step] == 0) {
+                       moveStack[moveSP++] = to + 11 | from << 8;
+                       if((range -= 8) <= 0) break;
+                   }
+               }
+           }
+           if(i < lowest) break; // suppresses back-rank Pawn drops in zh
+           dir = 2*firstDir[piece-WHITE];
            while((step = steps[dir++])) {
                int to = king, range = steps[dir++];
                if((range & 3) == 2) continue; // non-capture direction
@@ -924,7 +937,7 @@ CheckDrops (int stm, int king)
 void
 EvasionDrops (int stm, StackFrame *f, int mask)
 {
-    int i, x = f->checker, v = f->checkDir, s = stm ^ COLOR;
+    int i, j, x = f->checker, v = f->checkDir, s = stm ^ COLOR;
     while(board[x+=v] == 0) { // all squares on check ray
        int last = maxDrop;
        if((mask >>= 1) & 1) continue; // suppress 'futile interpositions'
@@ -937,6 +950,11 @@ EvasionDrops (int stm, StackFrame *f, int mask)
            }
            if(pawnCount[sqr2file[x]] & maxBulk[stm]) i += !i; // no Pawn in pawn-crowded file
        }
+       if(promoDrops) for(j=0; j<=maxDrop; j++) { // all droppable types
+           int piece = s + j, from = handSlot[piece];
+           if((signed char)board[from] < -1) // piece type is in hand
+               moveStack[moveSP++] = from << 8 | x + 11;
+       }
        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
@@ -958,6 +976,10 @@ AllDrops (int stm)
                if(stm == BLACK || !perpLoses) start = badZone;
                if(stm == WHITE || !perpLoses) end  -= badZone;
            }
+           if(promoDrops) { // for variants where pieces can be dropped with either side up
+               for(f=0; f<nrFiles; f++) for(r=0; r<boardEnd; r+=22) // no forbidden ranks then
+                   if(board[r+f] == 0) moveStack[moveSP++] = from << 8 | f + r + 11;
+           }
            for(f=0; f<nrFiles; f++) {
                if(i == 0 && pawnCount[f] & maxBulk[stm]) continue;
                for(r=start; r<end; r+=22)