Implement Teaching King move
authorH.G.Muller <hgm@hgm-xboard.(none)>
Fri, 6 May 2016 15:52:28 +0000 (17:52 +0200)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Fri, 6 May 2016 15:52:28 +0000 (17:52 +0200)
A new special-move code K is added, to indicate Lion-Dog move plus
infinite-range sliding. The code for generating captures, non-captures
and creating the attack map was streamlined a little; in particular
range captures on special moves are now table-driven.

hachu.c

diff --git a/hachu.c b/hachu.c
index 72d9972..ec25a6b 100644 (file)
--- a/hachu.c
+++ b/hachu.c
@@ -12,7 +12,7 @@
 \r
 #define VERSION "0.21"\r
 \r
-//define PATH level==0 || path[0] == 0x590cb &&  (level==1 || path[1] == 0x4c0c9 && (level == 2 || path[2] == 0x8598ca && (level == 3 /*|| path[3] == 0x3e865 && (level == 4 || path[4] == 0x4b865 && (level == 5))*/)))\r
+//define PATH level==0 || path[0] == 0x82906b &&  (level==1 || path[1] == 0x8790d9 && (level == 2 || path[2] == 0x8598ca && (level == 3 /*|| path[3] == 0x3e865 && (level == 4 || path[4] == 0x4b865 && (level == 5))*/)))\r
 #define PATH 0\r
 \r
 #define HASH\r
@@ -177,9 +177,9 @@ Move retMove, moveStack[20000], path[100], repStack[300], pv[1000], repeatMove[3
 #define N -1 /* Knight              */\r
 #define J -2 /* jump                */\r
 #define I -3 /* jump + step         */\r
-#define D -4 /* linear double move  */\r
+#define K -4 /* triple + range      */\r
 #define T -5 /* linear triple move  */\r
-#define K -6 /* triple + range      */\r
+#define D -6 /* linear double move  */\r
 #define L -7 /* true Lion move      */\r
 #define W -8 /* Werewolf move       */\r
 #define F -9 /* Lion + 3-step       */\r
@@ -358,7 +358,7 @@ PieceDesc makaPieces[] = {
   {"OM", "MW", 10, { 0,1,0,1,1,1,0,1 } }, // Old Monkey M'\r
   {"BB", "fB", 10, { 0,1,0,1,X,1,0,1 } }, // Blind Bear B'\r
   {"OR", "BA", 10, { 0,2,0,0,2,0,0,2 } }, // Old Rat O'\r
-  {"LD", "G", 10, { T,T,T,T,T,T,T,T } }, // Lion Dog W!\r
+  {"LD", "G", 800, { T,T,T,T,T,T,T,T } }, // Lion Dog W!\r
   {"WR", "G", 10, { 0,3,1,3,0,3,1,3 } }, // Wrestler W'\r
   {"GG", "G", 10, { 3,1,3,0,3,0,3,1 } }, // Guardian of the Gods G'\r
   {"BD", "G", 10, { 0,3,1,0,1,0,1,3 } }, // Budhist Devil D'\r
@@ -377,11 +377,11 @@ PieceDesc makaPieces[] = {
   {"fY", "", 10, { 0,X,0,0,X,0,0,X } }, // Free Tile +Y\r
   {"fU", "", 10, { 0,X,0,0,0,0,0,X } }, // Free Stone +U\r
   {"EM", "", 10, { 0,0,0,0,0,0,0,0 } }, // Emperor +K\r
-  {"TK", "", 10, { K,K,K,K,K,K,K,K } }, // Teaching King +I'\r
-  {"BS", "", 10, { S,S,S,S,S,S,S,S } }, // Budhist Spirit +J'\r
+  {"TK", "", 1300, { K,K,K,K,K,K,K,K }, 0, 6}, // Teaching King +I'\r
+  {"BS", "", 1500, { S,S,S,S,S,S,S,S }, 0, 7}, // Budhist Spirit +J'\r
   {"WS", "", 10, { X,X,0,X,1,X,0,X } }, // Wizard Stork +N'\r
   {"MW", "", 10, { 1,X,0,X,X,X,0,X } }, // Mountain Witch +M'\r
-  {"FF", "", 10, { F,F,F,F,F,F,F,F } }, // Furious Fiend +L!\r
+  {"FF", "", 1150, { F,F,F,F,F,F,F,F } }, // Furious Fiend +L!\r
   {"GD", "", 10, { 2,3,X,3,2,3,X,3 } }, // Great Dragon +W!\r
   {"GO", "", 10, { X,3,2,3,X,3,2,3 } }, // Golden Bird +X\r
   {"fW", "", 10, { X,X,X,0,0,0,X,X } }, // Free Wolf +W\r
@@ -984,6 +984,10 @@ SetUp (char *array, int var)
        p2 = LookUp(p1->promoted, var);\r
         m = AddPiece(color, p2);\r
        if(m <= n) n += 2;\r
+       if(p2->ranking > 5) { // contageous\r
+         AddPiece(color, p2);\r
+         if(m <= n) n += 2;\r
+       }\r
        p[n].promo = m;\r
        p[n].promoFlag = IsUpwardCompatible(p2->range, p1->range) * DONT_DEFER + CAN_PROMOTE;\r
        if(Forward(p1->range)) p[n].promoFlag |= LAST_RANK; // Pieces that only move forward can't defer on last rank\r
@@ -1311,10 +1315,9 @@ GenNonCapts (int promoSuppress)
              if(!occup & r < L) for(y=x+2*v; !NewNonCapture(x, y+=v, pFlag) && r == S; ); // BS and FF moves\r
              v = nStep[j];\r
              if(r != W) NewNonCapture(x, x + v, pFlag);\r
-           } else if(r == T) NewNonCapture(x, x+3*v, pFlag); // Lion Dog, also triple step\r
-           else if(r == K) {\r
+           } else if(r >= T) { // T or K\r
              occup |= NewNonCapture(x, x+3*v, pFlag); // Lion Dog, also triple step\r
-             if(!occup) for(y=x+3*v; !NewNonCapture(x, y+=v, pFlag); ); // TK moves\r
+             if(!occup && r == K) for(y=x+3*v; !NewNonCapture(x, y+=v, pFlag); ); // Teaching King distant moves\r
            }\r
          } else if(r == I) NewNonCapture(x, x + v, pFlag); // also do step\r
        } else\r
@@ -1355,18 +1358,18 @@ MapOneColor (int start, int last, int *map)
        if(r >= S) { // in any case, do a jump of 2\r
          if(board[x + 2*v] != EMPTY && board[x + 2*v] != EDGE)\r
            map[2*(x + 2*v) + start] += one[j], mob += (board[x + 2*v] ^ start) & 1;\r
-         if(r < J) { // Lion power, also single step\r
+         if(r < J) { // more than plain jump\r
            if(board[x + v] != EMPTY && board[x + v] != EDGE)\r
-             map[2*(x + v) + start] += one[j];\r
-           if(r < I) {\r
-           if(r == T || r == K) { // Lion Dog, also jump of 3\r
+             map[2*(x + v) + start] += one[j]; // single step (completes D and I)\r
+           if(r < I) {  // Lion power\r
+           if(r >= T) { // Lion Dog, also do a jump of 3\r
              if(board[x + 3*v] != EMPTY && board[x + 3*v] != EDGE)\r
                map[2*(x + 3*v) + start] += one[j];\r
-             if(r == K) { // also range (Teaching King)\r
+             if(r == K) { // Teaching King also range move\r
                int y = x, n = 0;\r
                while(1) {\r
                  if(board[y+=v] == EDGE) break;\r
-                 if(board[y] != EMPTY) {\r
+                 if(board[y] != EMPTY) {\r
                    if(n > 2) map[2*y + start] += one[j]; // outside Lion range\r
                    break;\r
                  }\r
@@ -1554,9 +1557,9 @@ MakeMove(Move m, UndoInfo *u)
 \r
   u->victim = board[u->to];\r
   p[u->victim].pos = ABSENT;\r
-  if(p[u->victim].ranking == 5 && p[u->piece].ranking < 4) { // contageous piece captured by non-royal\r
+  if(p[u->victim].ranking >= 5 && p[u->piece].ranking < 4) { // contageous piece captured by non-royal\r
     u->booty -= p[u->new].value;\r
-    u->new = u->piece & 1 | 2;    // promote to it\r
+    u->new = u->piece & 1 | (u->victim - 2 & ~3) + 2; // promote to it (assumes they head the list in pairs)\r
     if(p[u->new].pos != ABSENT) u->new += 2;\r
     p[u->piece].pos = ABSENT;\r
     u->booty += p[u->new].value;\r
@@ -1639,9 +1642,11 @@ GenCapts (int sqr, int victimValue)
       while( board[x+=v] == EMPTY ); // scan towards source until we encounter a 'stop'\r
 //printf("stop @ %c%d (dir %d)\n",x%BW+'a',x/BW,i);\r
       if((board[x] & TYPE) == stm) {               // stop is ours\r
+       static int minRange[20] = {  3, 0, 0, 0, 2, 2,  2 }; // K, T, D, L, W, F, S\r
+       static int maxRange[20] = { 36, 0, 0, 0, 3, 3, 36 }; // K, T, D, L, W, F, S\r
        int attacker = board[x], d = dist[x-sqr], r = p[attacker].range[i];\r
 //printf("attacker %d, range %d, dist %d\n", attacker, r, d);\r
-       if(r >= d || r < L && (d > 3 && r == S || d == 3 && r >= S)) { // it has a plain move in our direction that hits us\r
+       if(r >= d || r <= K && d <= maxRange[K-r] && d > minRange[K-r]) { // it has a plain move in our direction that hits us\r
          NewCapture(x, sqr + victimValue - SORTKEY(attacker), p[attacker].promoFlag);\r
          att -= one[i];\r
          if(!(att & attackMask[i])) continue; // no more; next direction\r
@@ -1649,7 +1654,7 @@ GenCapts (int sqr, int victimValue)
          while(board[x+=v] == EMPTY);// one attack accounted for, but more to come, so skip to next stop\r
        }\r
       }\r
-      // we get here when we are on a piece that dous not attack us through a (limited) ranging move,\r
+      // we get here when we are on a piece that does not attack us through a (limited) ranging move,\r
       // it can be our own or an enemy with not (enough) range, or which is blocked\r
       do {\r
 //printf("scan %x-%x (%d) dir=%d d=%d r=%d att=%o jcapt=%d qval=%d\n", sqr, x, board[x], i, dist[x-sqr], p[board[x]].range[i], att, jcapt, p[board[x]].qval);\r
@@ -2123,7 +2128,7 @@ if(PATH)printf("new iter %d\n", iterDep);
       bestScore = curEval; resDep = QSdepth;\r
       if(bestScore > alpha) {\r
        alpha = bestScore;\r
-if(PATH)printf("stand pat %d\n", bestScore);\r
+if(PATH)printf("stand pat %d (beta=%d)\n", bestScore, beta);\r
        if(bestScore >= beta) goto cutoff;\r
       }\r
     }\r
@@ -2131,14 +2136,18 @@ if(PATH)printf("stand pat %d\n", bestScore);
 if(flag && depth>= 0) printf("phase=%d: first/curr/last = %d / %d / %d\n", phase, firstMove, curMove, msp);fflush(stdout);\r
       // MOVE SOURCE\r
       if(curMove >= msp) { // we ran out of moves; generate some new\r
-if(PATH)printf("new moves, phase=%d\n", phase);\r
+if(PATH)printf("new moves, phase=%d\n", phase),fflush(stdout);\r
        switch(phase) {\r
          case 0: // null move\r
 #ifdef NULLMOVE\r
            if(depth > QSdepth && curEval >= beta && !inCheck && filling > 10) {\r
               int nullDep = depth - 3;\r
              stm ^= WHITE;\r
+path[level++] = 0;\r
+if(PATH) printf("%d:%d null move\n", level, depth),fflush(stdout);\r
              score = -Search(-beta, 1-beta, -difEval, nullDep<QSdepth ? QSdepth : nullDep, 0, promoSuppress & SQUARE, ABSENT, INF);\r
+if(PATH) printf("%d:%d null move score = %d\n", level, depth, score),fflush(stdout);\r
+level--;\r
              xstm = stm; stm ^= WHITE;\r
              if(score >= beta) { msp = oldMSP; retDep += 3; pvPtr = myPV; return score + (score < curEval); }\r
 //           else depth += lmr, lmr = 0;\r
@@ -2160,7 +2169,7 @@ if(PATH)printf("new moves, phase=%d\n", phase);
            nextVictim = xstm; autoFail = (depth == 0);\r
            phase = 3;\r
          case 3: // generate captures\r
-if(PATH) printf("%d:%2d:%2d next victim %d/%d\n",level,depth,iterDep,curMove,msp);\r
+if(PATH) printf("%d:%2d:%2d next victim %d/%d\n",level,depth,iterDep,curMove,msp),fflush(stdout);\r
            while(nextVictim < last[xstm]) {          // more victims exist\r
              int group, to = p[nextVictim += 2].pos; // take next\r
              if(to == ABSENT) continue;              // ignore if absent\r
@@ -2171,18 +2180,18 @@ if(PATH) printf("%d:%2d:%2d next victim %d/%d\n",level,depth,iterDep,curMove,msp
                if(bestScore < 2*group + curEval + 30) bestScore = 2*group + curEval + 30;\r
                goto cutoff;\r
              }\r
-if(PATH) printf("%d:%2d:%2d group=%d, to=%c%d\n",level,depth,iterDep,group,to%BW+'a',to/BW+ONE);\r
+if(PATH) printf("%d:%2d:%2d group=%d, to=%c%d\n",level,depth,iterDep,group,to%BW+'a',to/BW+ONE),fflush(stdout);\r
              GenCapts(to, 0);\r
-if(PATH) printf("%d:%2d:%2d first=%d msp=%d\n",level,depth,iterDep,firstMove,msp);\r
+if(PATH) printf("%d:%2d:%2d first=%d msp=%d\n",level,depth,iterDep,firstMove,msp),fflush(stdout);\r
              while(nextVictim < last[xstm] && p[nextVictim+2].value == group) { // more victims of same value exist\r
                to = p[nextVictim += 2].pos;          // take next\r
                if(to == ABSENT) continue;            // ignore if absent\r
                if(!attacks[2*to + stm]) continue;    // skip if not attacked\r
-if(PATH) printf("%d:%2d:%2d p=%d, to=%c%d\n",level,depth,iterDep,nextVictim,to%BW+'a',to/BW+ONE);\r
+if(PATH) printf("%d:%2d:%2d p=%d, to=%c%d\n",level,depth,iterDep,nextVictim,to%BW+'a',to/BW+ONE),fflush(stdout);\r
                GenCapts(to, 0);\r
-if(PATH) printf("%d:%2d:%2d msp=%d\n",level,depth,iterDep,msp);\r
+if(PATH) printf("%d:%2d:%2d msp=%d\n",level,depth,iterDep,msp),fflush(stdout);\r
              }\r
-if(PATH) printf("captures on %d generated, msp=%d, group=%d, threshold=%d\n", nextVictim, msp, group, threshold);\r
+if(PATH) printf("captures on %d generated, msp=%d, group=%d, threshold=%d\n", nextVictim, msp, group, threshold),fflush(stdout);\r
              goto extractMove; // in auto-fail phase, only search if they might auto-fail-hi\r
            }\r
 if(PATH) printf("# autofail=%d\n", autoFail);\r
@@ -2420,8 +2429,8 @@ pplist()
 {\r
   int i, j;\r
   for(i=0; i<182; i++) {\r
-       printf("%3d. %3d %3d %4d   %02x %d %d %x %3d %4d ", 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, p[i].pst);\r
-       for(j=0; j<8; j++) printf("  %2d", p[i].range[j]);\r
+       printf("%3d. %4d %3d %4d %02x %d %2d %x %3d %4d ", 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, p[i].pst);\r
+       for(j=0; j<8; j++) printf(" %3d", p[i].range[j]);\r
        if(i<2 || i>11) printf("\n"); else printf("  %02x %d\n", fireFlags[i-2]&255, p[i].ranking);\r
   }\r
   printf("last: %d / %d\nroyal %d / %d\n", last[WHITE], last[BLACK], royal[WHITE], royal[BLACK]);\r
@@ -2644,7 +2653,7 @@ MapFromScratch(attacks);
   for(i=listStart; i<msp && currentVariant == V_WOLF; i++) { // mark Werewolf captures as promotions\r
     int to = moveStack[i] & SQUARE, from = moveStack[i] >> SQLEN & SQUARE;\r
     if(to >= SPECIAL) continue;\r
-    if(p[board[to]].ranking == 5 && p[board[from]].ranking < 4) moveStack[i] |= PROMOTE;\r
+    if(p[board[to]].ranking >= 5 && p[board[from]].ranking < 4) moveStack[i] |= PROMOTE;\r
   }\r
 }\r
 \r
@@ -2950,12 +2959,14 @@ pboard(board);
             PrintResult(stm, score);\r
           } else {\r
             MOVE f, pMove = move;\r
+            static char *pName[] = { "w", "z", "j" };\r
             if((move & SQUARE) >= SPECIAL && p[board[f = move>>SQLEN & SQUARE]].value == pVal) { // e.p. capture\r
               pMove = move & ~SQUARE | f + toList[(move & SQUARE) - SPECIAL]; // print as a single move\r
             }\r
             stm = MakeMove2(stm, move);  // assumes MakeMove returns new side to move\r
             gameMove[moveNr++] = move;   // remember game\r
-            printf("move %s%s\n", MoveToText(pMove, 1), p[undoInfo.victim].ranking == 5 && p[undoInfo.piece].ranking < 4 ? "w" : "");\r
+            i = p[undoInfo.victim].ranking;\r
+            printf("move %s%s\n", MoveToText(pMove, 1), i == 5 && p[undoInfo.piece].ranking < 4 ? pName[i-5] : "");\r
             listEnd = 0;\r
             continue;                    // go check if we should ponder\r
           }\r
@@ -3084,8 +3095,8 @@ pboard(board);
                    "piece D& sbWfF\npiece V& FfW\npiece W& WfF\npiece S& sRvW\npiece R& FfRbW\npiece F& BfW\npiece X& FvWAvD\n"\r
                    "piece +D& WfF\npiece +V& FfsW\npiece +W& K\npiece +S& R\npiece +R& FvWAvD\npiece +F& BvRsW\npiece E& vRfF3bFsW\n");\r
           if(currentVariant == V_MACAD)\r
-            printf("setup (P.*B*RQSEXOG....D^J'..*LP'.L!J'...*W!...*F'...^C.C.^L!.^P'^K.T*L'.*C!*H!^I'.^E...*R'^P^T*W'*G'^G^SI'^X^OK"\r
-                          "p.*b*rqsexog....d^j'..*lp'.l!j'...*w!...*f'...^c.c.^l!.^p'^k.t*l'.*c!*h!^i'.^e...*r'^p^t*w'*g'^g^si'^x^ok) 13x13+0_chu %s w 0 1\n"\r
+            printf("setup (P.*B*RQSEXOG....D^J'..*LP'.L!J'=J...*W!...*F'...^C.C.^L!.^P'^K.T*L'.*C!*H!^I'=Z.^E...*R'^P^T*W'*G'^G^SI'^X^OK"\r
+                          "p.*b*rqsexog....d^j'..*lp'.l!j'=j...*w!...*f'...^c.c.^l!.^p'^k.t*l'.*c!*h!^i'=z.^e...*r'^p^t*w'*g'^g^si'^x^ok) 13x13+0_chu %s w 0 1\n"\r
                   "piece P& fW\npiece S& FfW\npiece E& FfsW\npiece X& WA\npiece O& FD\npiece G& WfF\npiece D& RF\npiece +J'& QNADcaKmabK\n"\r
                   "piece L& fR\npiece P'& vW\npiece L!& KNADcaKmabK\npiece J'& blfFrW\npiece H!& RmasR\npiece W!& KADcavKmcpafmcpavK\n"\r
                   "piece C!& BmasB\npiece F'& F2\npiece +C& vRfB\npiece C& vWfF\npiece +L!& K3NADcaKmabK\npiece +P'& vR\npiece T& FbsW\n"\r