Version 0.14: LMR, wing defense, Pawn blocking
authorH.G. Muller <h.g.muller@hccnet.nl>
Fri, 27 Sep 2013 12:09:06 +0000 (14:09 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Mon, 21 Oct 2013 08:40:26 +0000 (10:40 +0200)
Implement LMR. An eval term is added to keep the wings (L + RC) Lion proof.
A penalty is given for blocking own Pawns.

hachu.c

diff --git a/hachu.c b/hachu.c
index 56f1d9f..41af7d7 100644 (file)
--- a/hachu.c
+++ b/hachu.c
 // promotions by pieces with Lion power stepping in & out the zone in same turn\r
 // promotion on capture\r
 \r
-#define VERSION "0.13"\r
+#define VERSION "0.14e"\r
 \r
-#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))))*/)\r
+#define PATH level==0 /*|| path[0] == 0x3490a &&  (level==1 || path[1] == 0x285b3 && (level == 2 || path[2] == 0x8710f && (level == 3 /*|| path[3] == 0x3e865 && (level == 4 || path[4] == 0x4b865 && (level == 5)))))*/\r
 //define PATH 0\r
 \r
 #define HASH\r
 #define KILLERS\r
 #define NULLMOVE\r
 #define CHECKEXT\r
+#define LMR 4\r
 #define LIONTRAP\r
-#define XKINGSAFETY\r
+#define WINGS\r
+#define KINGSAFETY\r
+#define XFORTRESS\r
+#define PAWNBLOCK\r
 \r
 #include <stdio.h>\r
 #include <stdlib.h>\r
@@ -133,10 +137,11 @@ typedef struct {
   char fireMask;\r
 } UndoInfo;\r
 \r
-char *array, fenArray[4000], startPos[4000], *reason;\r
-int bWidth, bHeight, bsize, zone, currentVariant, chuFlag, tenFlag, chessFlag, repDraws, tsume, pvCuts;\r
+char *array, fenArray[4000], startPos[4000], *reason, checkStack[300];\r
+int bWidth, bHeight, bsize, zone, currentVariant, chuFlag, tenFlag, chessFlag, repDraws, tsume, pvCuts, allowRep, entryProm;\r
 int stm, xstm, hashKeyH=1, hashKeyL=1, framePtr, msp, nonCapts, rootEval, filling, promoDelta;\r
 int retMSP, retFirst, retDep, pvPtr, level, cnt50, mobilityScore;\r
+int ll, lr, ul, ur; // corner squares\r
 int nodes, startTime, lastRootMove, lastRootIter, tlim1, tlim2, tlim3, repCnt, comp, abortFlag;\r
 Move ponderMove;\r
 Move retMove, moveStack[10000], path[100], repStack[300], pv[1000], repeatMove[300], killer[100][2];\r
@@ -156,238 +161,238 @@ Move retMove, moveStack[10000], path[100], repStack[300], pv[1000], repeatMove[3
 #define C -10 /* capture only       */\r
 #define M -11 /* non-capture only   */\r
 \r
-#define LVAL 100 /* piece value of Lion. Used in chu for recognizing it to implement Lion-trade rules  */\r
-#define FVAL 500 /* piece value of Fire Demon. Used in code for recognizing moves with it and do burns */\r
+#define LVAL 1000 /* piece value of Lion. Used in chu for recognizing it to implement Lion-trade rules  */\r
+#define FVAL 5000 /* piece value of Fire Demon. Used in code for recognizing moves with it and do burns */\r
 \r
 PieceDesc chuPieces[] = {\r
-  {"LN", "", LVAL, { L,L,L,L,L,L,L,L }, 4 }, // lion\r
-  {"FK", "",   60, { X,X,X,X,X,X,X,X }, 4 }, // free king\r
-  {"SE", "",   55, { X,D,X,X,X,X,X,D }, 4 }, // soaring eagle\r
-  {"HF", "",   50, { D,X,X,X,X,X,X,X }, 4 }, // horned falcon\r
-  {"FO", "",   40, { X,X,0,X,X,X,0,X }, 4 }, // flying ox\r
-  {"FB", "",   40, { 0,X,X,X,0,X,X,X }, 4 }, // free boar\r
-  {"DK", "SE", 40, { X,1,X,1,X,1,X,1 }, 4 }, // dragon king\r
-  {"DH", "HF", 35, { 1,X,1,X,1,X,1,X }, 4 }, // dragon horse\r
-  {"WH", "",   35, { X,X,0,0,X,0,0,X }, 3 }, // white horse\r
-  {"R",  "DK", 30, { X,0,X,0,X,0,X,0 }, 4 }, // rook\r
-  {"FS", "",   30, { X,1,1,1,X,1,1,1 }, 3 }, // flying stag\r
-  {"WL", "",   25, { X,0,0,X,X,X,0,0 }, 4 }, // whale\r
-  {"K",  "",   28, { 1,1,1,1,1,1,1,1 }, 2, 4 }, // king\r
-  {"CP", "",   27, { 1,1,1,1,1,1,1,1 }, 2, 4 }, // king\r
-  {"B",  "DH", 25, { 0,X,0,X,0,X,0,X }, 2 }, // bishop\r
-  {"VM", "FO", 20, { X,0,1,0,X,0,1,0 }, 2 }, // vertical mover\r
-  {"SM", "FB", 20, { 1,0,X,0,1,0,X,0 }, 6 }, // side mover\r
-  {"DE", "CP", 20, { 1,1,1,1,0,1,1,1 }, 2 }, // drunk elephant\r
-  {"BT", "FS", 15, { 0,1,1,1,1,1,1,1 }, 2 }, // blind tiger\r
-  {"G",  "R",  15, { 1,1,1,0,1,0,1,1 }, 2 }, // gold\r
-  {"FL", "B",  15, { 1,1,0,1,1,1,0,1 }, 2 }, // ferocious leopard\r
-  {"KN", "LN", 15, { J,1,J,1,J,1,J,1 }, 2 }, // kirin\r
-  {"PH", "FK", 15, { 1,J,1,J,1,J,1,J }, 2 }, // phoenix\r
-  {"RV", "WL", 15, { X,0,0,0,X,0,0,0 }, 1 }, // reverse chariot\r
-  {"L",  "WH", 15, { X,0,0,0,0,0,0,0 }, 1 }, // lance\r
-  {"S",  "VM", 10, { 1,1,0,1,0,1,0,1 }, 2 }, // silver\r
-  {"C",  "SM", 10, { 1,1,0,0,1,0,0,1 }, 2 }, // copper\r
-  {"GB", "DE", 5,  { 1,0,0,0,1,0,0,0 }, 1 }, // go between\r
-  {"P",  "G",  4,  { 1,0,0,0,0,0,0,0 }, 2 }, // pawn\r
+  {"LN", "",  LVAL, { L,L,L,L,L,L,L,L }, 4 }, // lion\r
+  {"FK", "",   600, { X,X,X,X,X,X,X,X }, 4 }, // free king\r
+  {"SE", "",   550, { X,D,X,X,X,X,X,D }, 4 }, // soaring eagle\r
+  {"HF", "",   500, { D,X,X,X,X,X,X,X }, 4 }, // horned falcon\r
+  {"FO", "",   400, { X,X,0,X,X,X,0,X }, 4 }, // flying ox\r
+  {"FB", "",   400, { 0,X,X,X,0,X,X,X }, 4 }, // free boar\r
+  {"DK", "SE", 400, { X,1,X,1,X,1,X,1 }, 4 }, // dragon king\r
+  {"DH", "HF", 350, { 1,X,1,X,1,X,1,X }, 4 }, // dragon horse\r
+  {"WH", "",   350, { X,X,0,0,X,0,0,X }, 3 }, // white horse\r
+  {"R",  "DK", 300, { X,0,X,0,X,0,X,0 }, 4 }, // rook\r
+  {"FS", "",   300, { X,1,1,1,X,1,1,1 }, 3 }, // flying stag\r
+  {"WL", "",   250, { X,0,0,X,X,X,0,0 }, 4 }, // whale\r
+  {"K",  "",   280, { 1,1,1,1,1,1,1,1 }, 2, 4 }, // king\r
+  {"CP", "",   270, { 1,1,1,1,1,1,1,1 }, 2, 4 }, // king\r
+  {"B",  "DH", 250, { 0,X,0,X,0,X,0,X }, 2 }, // bishop\r
+  {"VM", "FO", 200, { X,0,1,0,X,0,1,0 }, 2 }, // vertical mover\r
+  {"SM", "FB", 200, { 1,0,X,0,1,0,X,0 }, 6 }, // side mover\r
+  {"DE", "CP", 201, { 1,1,1,1,0,1,1,1 }, 2 }, // drunk elephant\r
+  {"BT", "FS", 152, { 0,1,1,1,1,1,1,1 }, 2 }, // blind tiger\r
+  {"G",  "R",  151, { 1,1,1,0,1,0,1,1 }, 2 }, // gold\r
+  {"FL", "B",  150, { 1,1,0,1,1,1,0,1 }, 2 }, // ferocious leopard\r
+  {"KN", "LN", 154, { J,1,J,1,J,1,J,1 }, 2 }, // kirin\r
+  {"PH", "FK", 153, { 1,J,1,J,1,J,1,J }, 2 }, // phoenix\r
+  {"RV", "WL", 150, { X,0,0,0,X,0,0,0 }, 1 }, // reverse chariot\r
+  {"L",  "WH", 150, { X,0,0,0,0,0,0,0 }, 1 }, // lance\r
+  {"S",  "VM", 100, { 1,1,0,1,0,1,0,1 }, 2 }, // silver\r
+  {"C",  "SM", 100, { 1,1,0,0,1,0,0,1 }, 2 }, // copper\r
+  {"GB", "DE",  50, { 1,0,0,0,1,0,0,0 }, 1 }, // go between\r
+  {"P",  "G",   40, { 1,0,0,0,0,0,0,0 }, 2 }, // pawn\r
   { NULL }  // sentinel\r
 };\r
 \r
 PieceDesc shoPieces[] = {\r
-  {"DK", "",   70, { X,1,X,1,X,1,X,1 } }, // dragon king\r
-  {"DH", "",   52, { 1,X,1,X,1,X,1,X } }, // dragon horse\r
-  {"R",  "DK", 50, { X,0,X,0,X,0,X,0 } }, // rook\r
-  {"B",  "DH", 32, { 0,X,0,X,0,X,0,X } }, // bishop\r
-  {"K",  "",   41, { 1,1,1,1,1,1,1,1 } }, // king\r
-  {"CP", "",   40, { 1,1,1,1,1,1,1,1 } }, // king\r
-  {"DE", "CP", 25, { 1,1,1,1,0,1,1,1 } }, // silver\r
-  {"G",  "",   22, { 1,1,1,0,1,0,1,1 } }, // gold\r
-  {"S",  "G",  20, { 1,1,0,1,0,1,0,1 } }, // silver\r
-  {"L",  "G",  15, { X,0,0,0,0,0,0,0 } }, // lance\r
-  {"N",  "G",  11, { N,0,0,0,0,0,0,N } }, // Knight\r
-  {"P",  "G",  8,  { 1,0,0,0,0,0,0,0 } }, // pawn\r
+  {"DK", "",   700, { X,1,X,1,X,1,X,1 } }, // dragon king\r
+  {"DH", "",   520, { 1,X,1,X,1,X,1,X } }, // dragon horse\r
+  {"R",  "DK", 500, { X,0,X,0,X,0,X,0 } }, // rook\r
+  {"B",  "DH", 320, { 0,X,0,X,0,X,0,X } }, // bishop\r
+  {"K",  "",   410, { 1,1,1,1,1,1,1,1 } }, // king\r
+  {"CP", "",   400, { 1,1,1,1,1,1,1,1 } }, // king\r
+  {"DE", "CP", 250, { 1,1,1,1,0,1,1,1 } }, // silver\r
+  {"G",  "",   220, { 1,1,1,0,1,0,1,1 } }, // gold\r
+  {"S",  "G",  200, { 1,1,0,1,0,1,0,1 } }, // silver\r
+  {"L",  "G",  150, { X,0,0,0,0,0,0,0 } }, // lance\r
+  {"N",  "G",  110, { N,0,0,0,0,0,0,N } }, // Knight\r
+  {"P",  "G",   80, { 1,0,0,0,0,0,0,0 } }, // pawn\r
   { NULL }  // sentinel\r
 };\r
 \r
 PieceDesc daiPieces[] = {\r
-  {"FD", "G", 15, { 0,2,0,2,0,2,0,2 }, 2 }, // Flying Dragon\r
-  {"VO", "G", 20, { 2,0,2,0,2,0,2,0 }, 2 }, // Violent Ox\r
-  {"EW", "G",  8, { 1,1,1,0,0,0,1,1 }, 2 }, // Evil Wolf\r
-  {"CS", "G",  7, { 0,1,0,1,0,1,0,1 }, 1 }, // Cat Sword\r
-  {"AB", "G",  6, { 1,0,1,0,1,0,1,0 }, 1 }, // Angry Boar\r
-  {"I",  "G",  8, { 1,1,0,0,0,0,0,1 }, 2 }, // Iron\r
-  {"N",  "G",  6, { N,0,0,0,0,0,0,N }, 0 }, // Knight\r
-  {"ST", "G",  5, { 0,1,0,0,0,0,0,1 }, 0 }, // Stone\r
+  {"FD", "G", 150, { 0,2,0,2,0,2,0,2 }, 2 }, // Flying Dragon\r
+  {"VO", "G", 200, { 2,0,2,0,2,0,2,0 }, 2 }, // Violent Ox\r
+  {"EW", "G",  80, { 1,1,1,0,0,0,1,1 }, 2 }, // Evil Wolf\r
+  {"CS", "G",  70, { 0,1,0,1,0,1,0,1 }, 1 }, // Cat Sword\r
+  {"AB", "G",  60, { 1,0,1,0,1,0,1,0 }, 1 }, // Angry Boar\r
+  {"I",  "G",  80, { 1,1,0,0,0,0,0,1 }, 2 }, // Iron\r
+  {"N",  "G",  60, { N,0,0,0,0,0,0,N }, 0 }, // Knight\r
+  {"ST", "G",  50, { 0,1,0,0,0,0,0,1 }, 0 }, // Stone\r
   { NULL }  // sentinel\r
 };\r
 \r
 PieceDesc ddPieces[] = {\r
-  {"LO", "",   1, { 1,H,1,H,1,H,1,H } }, // Long-Nosed Goblin\r
-  {"OK", "LO", 1, { 2,1,2,0,2,0,2,1 } }, // Old Kite\r
-  {"PS", "HM", 1, { J,0,1,J,0,J,1,0 } }, // Poisonous Snake\r
-  {"GE", "",   1, { 3,3,5,5,3,5,5,3 } }, // Great Elephant\r
-  {"WS", "LD", 1, { 1,1,2,0,1,0,2,1 } }, // Western Barbarian\r
-  {"EA", "LN", 1, { 2,1,1,0,2,0,1,1 } }, // Eastern Barbarian\r
-  {"NO", "FE", 1, { 0,2,1,1,0,1,1,2 } }, // Northern Barbarian\r
-  {"SO", "WE", 1, { 0,1,1,2,0,2,1,1 } }, // Southern Barbarian\r
-  {"FE", "",   1, { 2,X,2,2,2,2,2,X } }, // Fragrant Elephant\r
-  {"WE", "",   1, { 2,2,2,X,2,X,2,2 } }, // White Elephant\r
-  {"FT", "",   1, { X,X,5,0,X,0,5,X } }, // Free Dream-Eater\r
-  {"FR", "",   1, { 5,X,X,0,5,0,X,X } }, // Free Demon\r
-  {"WB", "FT", 1, { 2,X,X,X,2,X,X,X } }, // Water Buffalo\r
-  {"RB", "FR", 1, { X,X,X,X,0,X,X,X } }, // Rushing Bird\r
-  {"SB", "",   1, { X,X,2,2,2,2,2,X } }, // Standard Bearer\r
-\r
-  {"FH", "FK", 1, { 1,2,1,0,1,0,1,2 } }, // Flying Horse\r
-  {"NK", "SB", 1, { 1,1,1,1,1,1,1,1 } }, // Neighbor King\r
-  {"BM", "MW", 1, { 0,1,1,1,0,1,1,1 } }, // Blind Monkey\r
-  {"DO", "",   1, { 2,X,2,X,2,X,2,X } }, // Dove\r
-  {"EB", "DO", 1, { 2,0,2,0,0,0,2,0 } }, // Enchanted Badger\r
-  {"EF", "SD", 1, { 0,2,0,0,2,0,0,2 } }, // Enchanted Fox\r
-  {"RA", "",   1, { X,0,X,1,X,1,X,0 } }, // Racing Chariot\r
-  {"SQ", "",   1, { X,1,X,0,X,0,X,1 } }, // Square Mover\r
-  {"PR", "SQ", 1, { 1,1,2,1,0,1,2,1 } }, // Prancing Stag\r
-  {"WT", "",   1, { X,1,2,0,X,0,2,X } }, // White Tiger\r
-  {"BD", "",   1, { 2,X,X,0,2,0,X,1 } }, // Blue Dragon\r
-  {"HD", "",   1, { X,0,0,0,1,0,0,0 } }, // Howling Dog\r
-  {"VB", "",   1, { 0,2,1,0,0,0,1,2 } }, // Violent Bear\r
-  {"SA", "",   1, { 2,1,0,0,2,0,0,1 } }, // Savage Tiger\r
-  {"W",  "",   1, { 0,2,0,0,0,0,0,2 } }, // Wood\r
-  {"CS", "DH",  7, { 0,1,0,1,0,1,0,1 } }, // cat sword\r
-  {"FD", "DK", 15, { 0,2,0,2,0,2,0,2 } }, // flying dragon\r
-  {"KN", "GD", 15, { J,1,J,1,J,1,J,1 } }, // kirin\r
-  {"PH", "GB", 15, { 1,J,1,J,1,J,1,J } }, // phoenix\r
-  {"LN", "FF",  100, { L,L,L,L,L,L,L,L } }, // lion\r
-  {"LD", "GE", 1, { T,T,T,T,T,T,T,T } }, // Lion Dog\r
-  {"AB", "", 1, { 1,0,1,0,1,0,1,0 } }, // Angry Boar\r
-  {"B",  "", 1, { 0,X,0,X,0,X,0,X } }, // Bishop\r
-  {"C",  "", 1, { 1,1,0,0,1,0,0,1 } }, // Copper\r
-  {"DH", "", 1, { 1,X,1,X,1,X,1,X } }, // Dragon Horse\r
-  {"DK", "", 1, { X,1,X,1,X,1,X,1 } }, // Dragon King\r
-  {"FK", "", 1, {  } }, // \r
-  {"EW", "", 1, { 1,1,1,0,0,0,1,1 } }, // Evil Wolf\r
-  {"FL", "", 1, {  } }, // \r
-  {"", "", 1, {  } }, // \r
-  {"", "", 1, {  } }, // \r
-  {"", "", 1, {  } }, // \r
-  {"", "", 1, {  } }, // \r
+  {"LO", "",   10, { 1,H,1,H,1,H,1,H } }, // Long-Nosed Goblin\r
+  {"OK", "LO", 10, { 2,1,2,0,2,0,2,1 } }, // Old Kite\r
+  {"PS", "HM", 10, { J,0,1,J,0,J,1,0 } }, // Poisonous Snake\r
+  {"GE", "",   10, { 3,3,5,5,3,5,5,3 } }, // Great Elephant\r
+  {"WS", "LD", 10, { 1,1,2,0,1,0,2,1 } }, // Western Barbarian\r
+  {"EA", "LN", 10, { 2,1,1,0,2,0,1,1 } }, // Eastern Barbarian\r
+  {"NO", "FE", 10, { 0,2,1,1,0,1,1,2 } }, // Northern Barbarian\r
+  {"SO", "WE", 10, { 0,1,1,2,0,2,1,1 } }, // Southern Barbarian\r
+  {"FE", "",   10, { 2,X,2,2,2,2,2,X } }, // Fragrant Elephant\r
+  {"WE", "",   10, { 2,2,2,X,2,X,2,2 } }, // White Elephant\r
+  {"FT", "",   10, { X,X,5,0,X,0,5,X } }, // Free Dream-Eater\r
+  {"FR", "",   10, { 5,X,X,0,5,0,X,X } }, // Free Demon\r
+  {"WB", "FT", 10, { 2,X,X,X,2,X,X,X } }, // Water Buffalo\r
+  {"RB", "FR", 10, { X,X,X,X,0,X,X,X } }, // Rushing Bird\r
+  {"SB", "",   10, { X,X,2,2,2,2,2,X } }, // Standard Bearer\r
+\r
+  {"FH", "FK", 10, { 1,2,1,0,1,0,1,2 } }, // Flying Horse\r
+  {"NK", "SB", 10, { 1,1,1,1,1,1,1,1 } }, // Neighbor King\r
+  {"BM", "MW", 10, { 0,1,1,1,0,1,1,1 } }, // Blind Monkey\r
+  {"DO", "",   10, { 2,X,2,X,2,X,2,X } }, // Dove\r
+  {"EB", "DO", 10, { 2,0,2,0,0,0,2,0 } }, // Enchanted Badger\r
+  {"EF", "SD", 10, { 0,2,0,0,2,0,0,2 } }, // Enchanted Fox\r
+  {"RA", "",   10, { X,0,X,1,X,1,X,0 } }, // Racing Chariot\r
+  {"SQ", "",   10, { X,1,X,0,X,0,X,1 } }, // Square Mover\r
+  {"PR", "SQ", 10, { 1,1,2,1,0,1,2,1 } }, // Prancing Stag\r
+  {"WT", "",   10, { X,1,2,0,X,0,2,X } }, // White Tiger\r
+  {"BD", "",   10, { 2,X,X,0,2,0,X,1 } }, // Blue Dragon\r
+  {"HD", "",   10, { X,0,0,0,1,0,0,0 } }, // Howling Dog\r
+  {"VB", "",   10, { 0,2,1,0,0,0,1,2 } }, // Violent Bear\r
+  {"SA", "",   10, { 2,1,0,0,2,0,0,1 } }, // Savage Tiger\r
+  {"W",  "",   10, { 0,2,0,0,0,0,0,2 } }, // Wood\r
+  {"CS", "DH",  70, { 0,1,0,1,0,1,0,1 } }, // cat sword\r
+  {"FD", "DK", 150, { 0,2,0,2,0,2,0,2 } }, // flying dragon\r
+  {"KN", "GD", 150, { J,1,J,1,J,1,J,1 } }, // kirin\r
+  {"PH", "GB", 150, { 1,J,1,J,1,J,1,J } }, // phoenix\r
+  {"LN", "FF",  1000, { L,L,L,L,L,L,L,L } }, // lion\r
+  {"LD", "GE", 10, { T,T,T,T,T,T,T,T } }, // Lion Dog\r
+  {"AB", "", 10, { 1,0,1,0,1,0,1,0 } }, // Angry Boar\r
+  {"B",  "", 10, { 0,X,0,X,0,X,0,X } }, // Bishop\r
+  {"C",  "", 10, { 1,1,0,0,1,0,0,1 } }, // Copper\r
+  {"DH", "", 10, { 1,X,1,X,1,X,1,X } }, // Dragon Horse\r
+  {"DK", "", 10, { X,1,X,1,X,1,X,1 } }, // Dragon King\r
+  {"FK", "", 10, {  } }, // \r
+  {"EW", "", 10, { 1,1,1,0,0,0,1,1 } }, // Evil Wolf\r
+  {"FL", "", 10, {  } }, // \r
+  {"", "", 10, {  } }, // \r
+  {"", "", 10, {  } }, // \r
+  {"", "", 10, {  } }, // \r
+  {"", "", 10, {  } }, // \r
   { NULL }  // sentinel\r
 };\r
 \r
 PieceDesc makaPieces[] = {\r
-  {"DV", "", 1, { 0,1,0,1,0,0,1,1 } }, // Deva\r
-  {"DS", "", 1, { 0,1,1,0,0,1,0,1 } }, // Dark Spirit\r
-  {"T",  "", 1, { 0,1,0,0,1,0,0,1 } }, // Tile\r
-  {"CS", "", 1, { 1,0,0,1,1,1,0,0 } }, // Coiled Serpent\r
-  {"RD", "", 1, { 1,0,1,1,1,1,1,0 } }, // Reclining Dragon\r
-  {"CC", "", 1, { 0,1,1,0,1,0,1,1 } }, // Chinese Cock\r
-  {"OM", "", 1, { 0,1,0,1,1,1,0,1 } }, // Old Monkey\r
-  {"BB", "", 1, { 0,1,0,1,X,1,0,1 } }, // Blind Bear\r
-  {"OR", "", 1, { 0,2,0,0,2,0,0,2 } }, // Old Rat\r
-  {"LD", "WS", 1, { T,T,T,T,T,T,T,T } }, // Lion Dog\r
-  {"WR", "", 1, { 0,3,1,3,0,3,1,3 } }, // Wrestler\r
-  {"GG", "", 1, { 3,1,3,0,3,0,3,1 } }, // Guardian of the Gods\r
-  {"BD", "", 1, { 0,3,1,0,1,0,1,3 } }, // Budhist Devil\r
-  {"SD", "", 1, { 5,2,5,2,5,2,5,2 } }, // She-Devil\r
-  {"DY", "", 1, { J,0,1,0,J,0,1,0 } }, // Donkey\r
-  {"CP", "", 1, { 0,H,0,2,0,2,0,H } }, // Capricorn\r
-  {"HM", "", 1, { H,0,H,0,H,0,H,0 } }, // Hook Mover\r
-  {"SF", "", 1, { 0,1,X,1,0,1,0,1 } }, // Side Flier\r
-  {"LC", "", 1, { X,0,0,X,1,0,0,X } }, // Left Chariot\r
-  {"RC", "", 1, { X,X,0,0,1,X,0,0 } }, // Right Chariot\r
-  {"FG", "", 1, { X,X,X,0,X,0,X,X } }, // Free Gold\r
-  {"FS", "", 1, { X,X,0,X,0,X,0,X } }, // Free Silver\r
-  {"FC", "", 1, { X,X,0,0,X,0,0,X } }, // Free Copper\r
-  {"FI", "", 1, { X,X,0,0,0,0,0,X } }, // Free Iron\r
-  {"FT", "", 1, { 0,X,0,0,X,0,0,X } }, // Free Tile\r
-  {"FN", "", 1, { 0,X,0,0,0,0,0,X } }, // Free Stone\r
-  {"FTg", "", 1, { 0,X,X,X,X,X,X,X } }, // Free Tiger\r
-  {"FLp", "", 1, { X,X,0,X,X,X,0,X } }, // Free Leopard (Free Boar?)\r
-  {"FSp", "", 1, { X,0,0,X,X,X,0,0 } }, // Free Serpent (Whale?)\r
-  {"FrD", "", 1, { X,0,X,X,X,X,X,0 } }, // Free Dragon\r
-  {"FC", "", 1, { 0,X,0,X,0,X,0,X } }, // Free Cat (Bishop?)\r
-  {"EM", "", 1, {  } }, // Emperor\r
-  {"TK", "", 1, {  } }, // Teaching King\r
-  {"BS", "", 1, {  } }, // Budhist Spirit\r
-  {"WS", "", 1, { X,X,0,X,1,X,0,X } }, // Wizard Stork\r
-  {"MW", "", 1, { 1,X,0,X,X,X,0,X } }, // Mountain Witch\r
-  {"FF", "", 1, {  } }, // Furious Fiend\r
-  {"GD", "", 1, { 2,3,X,3,2,3,X,3 } }, // Great Dragon\r
-  {"GB", "", 1, { X,3,2,3,X,3,2,3 } }, // Golden Bird\r
-  {"FrW", "", 1, {  } }, // Free Wolf\r
-  {"FrB", "", 1, {  } }, // Free Bear\r
-  {"BT", "", 1, { X,0,0,X,0,X,0,0 } }, // Bat\r
-  {"", "", 1, {  } }, // \r
+  {"DV", "", 10, { 0,1,0,1,0,0,1,1 } }, // Deva\r
+  {"DS", "", 10, { 0,1,1,0,0,1,0,1 } }, // Dark Spirit\r
+  {"T",  "", 10, { 0,1,0,0,1,0,0,1 } }, // Tile\r
+  {"CS", "", 10, { 1,0,0,1,1,1,0,0 } }, // Coiled Serpent\r
+  {"RD", "", 10, { 1,0,1,1,1,1,1,0 } }, // Reclining Dragon\r
+  {"CC", "", 10, { 0,1,1,0,1,0,1,1 } }, // Chinese Cock\r
+  {"OM", "", 10, { 0,1,0,1,1,1,0,1 } }, // Old Monkey\r
+  {"BB", "", 10, { 0,1,0,1,X,1,0,1 } }, // Blind Bear\r
+  {"OR", "", 10, { 0,2,0,0,2,0,0,2 } }, // Old Rat\r
+  {"LD", "WS", 10, { T,T,T,T,T,T,T,T } }, // Lion Dog\r
+  {"WR", "", 10, { 0,3,1,3,0,3,1,3 } }, // Wrestler\r
+  {"GG", "", 10, { 3,1,3,0,3,0,3,1 } }, // Guardian of the Gods\r
+  {"BD", "", 10, { 0,3,1,0,1,0,1,3 } }, // Budhist Devil\r
+  {"SD", "", 10, { 5,2,5,2,5,2,5,2 } }, // She-Devil\r
+  {"DY", "", 10, { J,0,1,0,J,0,1,0 } }, // Donkey\r
+  {"CP", "", 10, { 0,H,0,2,0,2,0,H } }, // Capricorn\r
+  {"HM", "", 10, { H,0,H,0,H,0,H,0 } }, // Hook Mover\r
+  {"SF", "", 10, { 0,1,X,1,0,1,0,1 } }, // Side Flier\r
+  {"LC", "", 10, { X,0,0,X,1,0,0,X } }, // Left Chariot\r
+  {"RC", "", 10, { X,X,0,0,1,X,0,0 } }, // Right Chariot\r
+  {"FG", "", 10, { X,X,X,0,X,0,X,X } }, // Free Gold\r
+  {"FS", "", 10, { X,X,0,X,0,X,0,X } }, // Free Silver\r
+  {"FC", "", 10, { X,X,0,0,X,0,0,X } }, // Free Copper\r
+  {"FI", "", 10, { X,X,0,0,0,0,0,X } }, // Free Iron\r
+  {"FT", "", 10, { 0,X,0,0,X,0,0,X } }, // Free Tile\r
+  {"FN", "", 10, { 0,X,0,0,0,0,0,X } }, // Free Stone\r
+  {"FTg", "", 10, { 0,X,X,X,X,X,X,X } }, // Free Tiger\r
+  {"FLp", "", 10, { X,X,0,X,X,X,0,X } }, // Free Leopard (Free Boar?)\r
+  {"FSp", "", 10, { X,0,0,X,X,X,0,0 } }, // Free Serpent (Whale?)\r
+  {"FrD", "", 10, { X,0,X,X,X,X,X,0 } }, // Free Dragon\r
+  {"FC", "", 10, { 0,X,0,X,0,X,0,X } }, // Free Cat (Bishop?)\r
+  {"EM", "", 10, {  } }, // Emperor\r
+  {"TK", "", 10, {  } }, // Teaching King\r
+  {"BS", "", 10, {  } }, // Budhist Spirit\r
+  {"WS", "", 10, { X,X,0,X,1,X,0,X } }, // Wizard Stork\r
+  {"MW", "", 10, { 1,X,0,X,X,X,0,X } }, // Mountain Witch\r
+  {"FF", "", 10, {  } }, // Furious Fiend\r
+  {"GD", "", 10, { 2,3,X,3,2,3,X,3 } }, // Great Dragon\r
+  {"GB", "", 10, { X,3,2,3,X,3,2,3 } }, // Golden Bird\r
+  {"FrW", "", 10, {  } }, // Free Wolf\r
+  {"FrB", "", 10, {  } }, // Free Bear\r
+  {"BT", "", 10, { X,0,0,X,0,X,0,0 } }, // Bat\r
+  {"", "", 10, {  } }, // \r
   { NULL }  // sentinel\r
 };\r
 \r
 PieceDesc taiPieces[] = {\r
-  {"", "", 1, {  } }, // Peacock\r
-  {"", "", 1, {  } }, // Vermillion Sparrow\r
-  {"", "", 1, {  } }, // Turtle Snake\r
-  {"", "", 1, {  } }, // Silver Hare\r
-  {"", "", 1, {  } }, // Golden Deer\r
-  {"", "", 1, {  } }, // \r
-  {"", "", 1, {  } }, // \r
-  {"", "", 1, {  } }, // \r
+  {"", "", 10, {  } }, // Peacock\r
+  {"", "", 10, {  } }, // Vermillion Sparrow\r
+  {"", "", 10, {  } }, // Turtle Snake\r
+  {"", "", 10, {  } }, // Silver Hare\r
+  {"", "", 10, {  } }, // Golden Deer\r
+  {"", "", 10, {  } }, // \r
+  {"", "", 10, {  } }, // \r
+  {"", "", 10, {  } }, // \r
   { NULL }  // sentinel\r
 };\r
 \r
 PieceDesc tenjikuPieces[] = { // only those not in Chu, or different (because of different promotion)\r
-  {"FI", "", FVAL, { X,X,0,X,X,X,0,X } }, // Fire Demon\r
-  {"GG", "", 150, { R,R,R,R,R,R,R,R }, 0, 3 }, // Great General\r
-  {"VG", "", 140, { 0,R,0,R,0,R,0,R }, 0, 2 }, // Vice General\r
-  {"RG", "GG",120, { R,0,R,0,R,0,R,0 }, 0, 1 }, // Rook General\r
-  {"BG", "VG",110, { 0,R,0,R,0,R,0,R }, 0, 1 }, // Bishop General\r
-  {"SE", "RG", 1, { X,D,X,X,X,X,X,D } }, // Soaring Eagle\r
-  {"HF", "BG", 1, { D,X,X,X,X,X,X,X } }, // Horned Falcon\r
-  {"LH", "",   1, { L,S,L,S,L,S,L,S } }, // Lion-Hawk\r
-  {"LN", "LH", LVAL, { L,L,L,L,L,L,L,L } }, // Lion\r
+  {"FI", "",  FVAL, { X,X,0,X,X,X,0,X } }, // Fire Demon\r
+  {"GG", "",  1500, { R,R,R,R,R,R,R,R }, 0, 3 }, // Great General\r
+  {"VG", "",  1400, { 0,R,0,R,0,R,0,R }, 0, 2 }, // Vice General\r
+  {"RG", "GG",1200, { R,0,R,0,R,0,R,0 }, 0, 1 }, // Rook General\r
+  {"BG", "VG",1100, { 0,R,0,R,0,R,0,R }, 0, 1 }, // Bishop General\r
+  {"SE", "RG", 10, { X,D,X,X,X,X,X,D } }, // Soaring Eagle\r
+  {"HF", "BG", 10, { D,X,X,X,X,X,X,X } }, // Horned Falcon\r
+  {"LH", "",   10, { L,S,L,S,L,S,L,S } }, // Lion-Hawk\r
+  {"LN", "LH",LVAL, { L,L,L,L,L,L,L,L } }, // Lion\r
   {"FE", "",   1,   { X,X,X,X,X,X,X,X } }, // Free Eagle\r
-  {"FK", "FE",  60, { X,X,X,X,X,X,X,X } }, // Free King\r
-  {"HT", "",   1, { X,X,2,X,X,X,2,X } }, // Heavenly Tetrarchs\r
-  {"CS", "HT", 1, { X,X,2,X,X,X,2,X } }, // Chariot Soldier\r
-  {"WB", "FI", 1, { 2,X,X,X,2,X,X,X } }, // Water Buffalo\r
-  {"VS", "CS", 1, { X,0,2,0,1,0,2,0 } }, // Vertical Soldier\r
-  {"SS", "WB", 1, { 2,0,X,0,1,0,X,0 } }, // Side Soldier\r
-  {"I",  "VS", 1, { 1,1,0,0,0,0,0,1 } }, // Iron\r
-  {"N",  "SS", 1, { N,0,0,0,0,0,0,N } }, // Knight\r
-  {"MG", "",   1, { X,0,0,X,0,X,0,0 } }, // Multi-General\r
-  {"D",  "MG", 1, { 1,0,0,1,0,1,0,0 } }, // Dog\r
+  {"FK", "FE", 600, { X,X,X,X,X,X,X,X } }, // Free King\r
+  {"HT", "",   10, { X,X,2,X,X,X,2,X } }, // Heavenly Tetrarchs\r
+  {"CS", "HT", 10, { X,X,2,X,X,X,2,X } }, // Chariot Soldier\r
+  {"WB", "FI", 10, { 2,X,X,X,2,X,X,X } }, // Water Buffalo\r
+  {"VS", "CS", 10, { X,0,2,0,1,0,2,0 } }, // Vertical Soldier\r
+  {"SS", "WB", 10, { 2,0,X,0,1,0,X,0 } }, // Side Soldier\r
+  {"I",  "VS", 10, { 1,1,0,0,0,0,0,1 } }, // Iron\r
+  {"N",  "SS", 10, { N,0,0,0,0,0,0,N } }, // Knight\r
+  {"MG", "",   10, { X,0,0,X,0,X,0,0 } }, // Multi-General\r
+  {"D",  "MG", 10, { 1,0,0,1,0,1,0,0 } }, // Dog\r
   { NULL }  // sentinel\r
 };\r
 \r
 PieceDesc taikyokuPieces[] = {\r
-  {"", "", 1, {  } }, // \r
+  {"", "", 10, {  } }, // \r
   { NULL }  // sentinel\r
 };\r
 \r
 PieceDesc chessPieces[] = {\r
-  {"Q", "",  95, { X,X,X,X,X,X,X,X } },\r
-  {"R", "",  50, { X,0,X,0,X,0,X,0 } },\r
-  {"B", "",  32, { 0,X,0,X,0,X,0,X } },\r
-  {"N", "",  30, { N,N,N,N,N,N,N,N } },\r
-  {"K", "",  28, { 1,1,1,1,1,1,1,1 } },\r
-  {"P", "Q",  8, { M,C,0,0,0,0,0,C } },\r
+  {"Q", "",  950, { X,X,X,X,X,X,X,X } },\r
+  {"R", "",  500, { X,0,X,0,X,0,X,0 } },\r
+  {"B", "",  320, { 0,X,0,X,0,X,0,X } },\r
+  {"N", "",  300, { N,N,N,N,N,N,N,N } },\r
+  {"K", "",  280, { 1,1,1,1,1,1,1,1 } },\r
+  {"P", "Q",  80, { M,C,0,0,0,0,0,C } },\r
   { NULL }  // sentinel\r
 };\r
 \r
 PieceDesc shatranjPieces[] = {\r
-  {"FK", "", 15, { 0,1,0,1,0,1,0,1 } },\r
-  {"R", "",  50, { X,0,X,0,X,0,X,0 } },\r
-  {"B", "",   9, { 0,J,0,J,0,J,0,J } },\r
-  {"N", "",  30, { N,N,N,N,N,N,N,N } },\r
-  {"K", "",  28, { 1,1,1,1,1,1,1,1 } },\r
-  {"P", "FK", 8, { M,C,0,0,0,0,0,C } },\r
+  {"FK", "", 150, { 0,1,0,1,0,1,0,1 } },\r
+  {"R", "",  500, { X,0,X,0,X,0,X,0 } },\r
+  {"B", "",   90, { 0,J,0,J,0,J,0,J } },\r
+  {"N", "",  300, { N,N,N,N,N,N,N,N } },\r
+  {"K", "",  280, { 1,1,1,1,1,1,1,1 } },\r
+  {"P", "FK", 80, { M,C,0,0,0,0,0,C } },\r
   { NULL }  // sentinel\r
 };\r
 \r
 PieceDesc makrukPieces[] = {\r
-  {"SM","",  15, { 0,1,0,1,0,1,0,1 } },\r
-  {"R", "",  50, { X,0,X,0,X,0,X,0 } },\r
-  {"S", "",  20, { 1,1,0,1,0,1,0,1 } }, // silver\r
-  {"N", "",  30, { N,N,N,N,N,N,N,N } },\r
-  {"K", "",  28, { 1,1,1,1,1,1,1,1 } },\r
-  {"P", "SM", 8, { M,C,0,0,0,0,0,C } },\r
+  {"SM","",  150, { 0,1,0,1,0,1,0,1 } },\r
+  {"R", "",  500, { X,0,X,0,X,0,X,0 } },\r
+  {"S", "",  200, { 1,1,0,1,0,1,0,1 } }, // silver\r
+  {"N", "",  300, { N,N,N,N,N,N,N,N } },\r
+  {"K", "",  280, { 1,1,1,1,1,1,1,1 } },\r
+  {"P", "SM", 80, { M,C,0,0,0,0,0,C } },\r
   { NULL }  // sentinel\r
 };\r
 \r
@@ -620,7 +625,7 @@ void
 SqueezeOut (int n)\r
 { // remove piece number n from the mentioned side's piece list (and adapt the reference to the displaced pieces!)\r
   int i;\r
-  for(i=stm+2; i<last[stm]; i+=2)\r
+  for(i=stm+2; i<=last[stm]; i+=2)\r
     if(p[i].promo > n) p[i].promo -= 2;\r
   for(i=n; i<last[stm]; i+=2) {\r
     p[i] = p[i+2];\r
@@ -702,8 +707,8 @@ StackMultis (int col)
 {\r
   int i, j;\r
   multis[col] = col;\r
-  for(i=col+2; i<last[col]; i+=2) { // scan piece list for multi-capturers\r
-    for(j=0; j<8; j++) if(p[i].range[j] < J && p[i].range[j] >= S || p[i].value == 10*FVAL) {\r
+  for(i=col+2; i<=last[col]; i+=2) { // scan piece list for multi-capturers\r
+    for(j=0; j<8; j++) if(p[i].range[j] < J && p[i].range[j] >= S || p[i].value == FVAL) {\r
       multiMovers[multis[col]] = i; // found one: put its piece number in list\r
       multis[col] += 2;\r
       break;\r
@@ -715,13 +720,13 @@ void
 Compactify (int stm)\r
 { // remove pieces that are permanently gone (captured or promoted) from one side's piece list\r
   int i, j, k;\r
-  for(i=stm+2; i<last[stm]; i+=2) { // first pass: unpromoted pieces\r
+  for(i=stm+2; i<=last[stm]; i+=2) { // first pass: unpromoted pieces\r
     if((k = p[i].promo) >= 0 && p[i].pos == ABSENT) { // unpromoted piece no longer there\r
       p[k].promo = -2; // orphan promoted version\r
       SqueezeOut(i);\r
     }\r
   }\r
-  for(i=stm+2; i<last[stm]; i+=2) { // second pass: promoted pieces\r
+  for(i=stm+2; i<=last[stm]; i+=2) { // second pass: promoted pieces\r
 \r
     if((k = p[i].promo) == -2 && p[i].pos == ABSENT) { // orphaned promoted piece not present\r
       SqueezeOut(i);\r
@@ -735,11 +740,11 @@ AddPiece (int stm, PieceDesc *list)
 {\r
   int i, j, *key, v;\r
   for(i=stm+2; i<=last[stm]; i += 2) {\r
-    if(p[i].value < 10*list->value || p[i].value == 10*list->value && (p[i].promo < 0)) break;\r
+    if(p[i].value < list->value || p[i].value == list->value && (p[i].promo < 0)) break;\r
   }\r
   last[stm] += 2;\r
   for(j=last[stm]; j>i; j-= 2) p[j] = p[j-2];\r
-  p[i].value = v = 10*list->value;\r
+  p[i].value = v = list->value;\r
   for(j=0; j<8; j++) p[i].range[j] = list->range[j^4*(WHITE-stm)];\r
   switch(Range(p[i].range)) {\r
     case 1:  p[i].pst = BH; break;\r
@@ -753,7 +758,7 @@ AddPiece (int stm, PieceDesc *list)
   p[i].promoFlag = 0;\r
   p[i].bulk = list->bulk;\r
   p[i].mobWeight = v > 600 ? 0 : v >= 400 ? 1 : v >= 300 ? 2 : v > 150 ? 3 : v >= 100 ? 2 : 0;\r
-  if(Lance(list->range),0)\r
+  if(Lance(list->range))\r
     p[i].mobWeight = 5 + 3*(list->range[4]==X), p[i].pst = 0; // clear path but don't move forward\r
   for(j=stm+2; j<= last[stm]; j+=2) {\r
     if(p[j].promo >= i) p[j].promo += 2;\r
@@ -806,7 +811,7 @@ SetUp(char *array, int var)
        p[n].promoFlag &= n&1 ? P_WHITE : P_BLACK;\r
        p[m].promo = -1;\r
        p[m].pos = ABSENT;\r
-       if(p[m].value == 10*LVAL) kylin[color] = n; // remember piece that promotes to Lion\r
+       if(p[m].value == LVAL) kylin[color] = n; // remember piece that promotes to Lion\r
       } else p[n].promo = -1; // unpromotable piece\r
 //printf("piece = %c%-2s %d(%d) %d/%d\n", color ? 'w' : 'b', name, n, m, last[color], last[!color]);\r
     }\r
@@ -816,7 +821,7 @@ SetUp(char *array, int var)
   if(!(prince & WHITE+1)) p[AddPiece(WHITE, LookUp("CP", V_CHU))].pos = ABSENT;\r
   if(!(prince & BLACK+1)) p[AddPiece(BLACK, LookUp("CP", V_CHU))].pos = ABSENT;\r
   for(i=0; i<8; i++)  fireFlags[i] = 0;\r
-  for(i=2, n=1; i<10; i++) if(p[i].value == 10*FVAL) {\r
+  for(i=2, n=1; i<10; i++) if(p[i].value == FVAL) {\r
     int x = p[i].pos; // mark all burn zones\r
     fireFlags[i-2] = n;\r
     if(x != ABSENT) for(j=0; j<8; j++) fireBoard[x+kStep[j]] |= n;\r
@@ -868,6 +873,7 @@ Init (int var)
   tenFlag = (currentVariant == V_TENJIKU);\r
   chessFlag = (currentVariant == V_CHESS);\r
   repDraws  = (currentVariant == V_CHESS || currentVariant == V_SHATRANJ || currentVariant == V_MAKRUK);\r
+  ll = 0; lr = bHeight - 1; ul = (bHeight - 1)*bWidth; ur = ul + bHeight - 1;\r
 \r
   for(i= -1; i<9; i++) { // board steps in linear coordinates\r
     kStep[i] = STEP(direction[i&7].x,   direction[i&7].y);       // King\r
@@ -921,12 +927,12 @@ Init (int var)
   for(j=0; j<BH; j++) {\r
    for(i=0; i<BH; i++) {\r
     int s = BW*i + j, d = BH*(BH-2) - abs(2*i - BH + 1)*(BH-1) - (2*j - BH + 1)*(2*j - BH + 1);\r
-    PST[s] = 0;\r
+    PST[s] = 2*(i==0 | i==BH-1) + (i==1 | i==BH-2); // last-rank markers in null table\r
     PST[BH+s] = d/4 - (i == 0 || i == BH-1 ? 5 : 0) - (j == 0 || j == BH-1 ? 5 : 0)\r
                     + 2*(i==zone || i==BH-zone-1);  // stepper centralization\r
     PST[BH*BW+s] = d/6;                             // double-stepper centralization\r
     PST[BH*BW+BH+s] = d/12;                         // slider centralization\r
-    PST[2*BH*BW+s] = j < 3 || j > BH-4 ? (i < 3 ? 5 : i == 3 ? 2 : i == 4 ? 1 : 0) : 0;\r
+    PST[2*BH*BW+s] = j < 3 || j > BH-4 ? (i < 3 ? 7 : i == 3 ? 4 : i == 4 ? 2 : 0) : 0;\r
     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;\r
     PST[3*BH*BW+s] = PST[3*BH*BW+BH+s] = PST[BH+s]; // as stepper, but with pre-promotion bonus W/B\r
    }\r
@@ -971,7 +977,8 @@ NewNonCapture (int x, int y, int promoFlags)
 {\r
   if(board[y] != EMPTY) return 1; // edge, capture or own piece\r
 //if(flag) printf("# add %c%d%c%d, pf=%d\n", x%BW+'a',x/BW,y%BW+'a',y/BW, promoFlags);\r
-  if( (promoBoard[x] | promoBoard[y]) & promoFlags) { // piece can promote with this move\r
+  if( (promoBoard[x] | promoBoard[y]) & promoFlags &&\r
+      (!entryProm || promoBoard[y] & ~promoBoard[x] & CAN_PROMOTE )){ // piece can promote with this move\r
     moveStack[msp++] = moveStack[nonCapts];           // create space for promotion\r
     moveStack[nonCapts++] = x<<SQLEN | y | PROMOTE;   // push promotion\r
     if((promoFlags & promoBoard[y] & (CANT_DEFER | DONT_DEFER | LAST_RANK)) == 0) { // deferral could be a better alternative\r
@@ -1401,7 +1408,7 @@ MakeMove(Move m, UndoInfo *u)
   if(p[u->piece].promoFlag & LAST_RANK) cnt50 = 0; // forward piece: move is irreversible\r
   // TODO: put in some test for forward moves of non-backward pieces?\r
 \r
-  if(p[u->piece].value == 10*FVAL) { // move with Fire Demon\r
+  if(p[u->piece].value == FVAL) { // move with Fire Demon\r
     int i, f=~fireFlags[u->piece-2];\r
     for(i=0; i<8; i++) fireBoard[u->from + kStep[i]] &= f; // clear old burn zone\r
   }\r
@@ -1443,7 +1450,7 @@ MakeMove(Move m, UndoInfo *u)
     hashKeyH ^= p[u->epVictim[0]].pieceKey * squareKey[u->epSquare+BH];\r
     hashKeyL ^= p[u->epVictim[1]].pieceKey * squareKey[u->ep2Square];\r
     hashKeyH ^= p[u->epVictim[1]].pieceKey * squareKey[u->ep2Square+BH];\r
-    if(p[u->piece].value != 10*LVAL && p[u->epVictim[0]].value == 10*LVAL) deferred |= PROMOTE; // flag non-Lion x Lion\r
+    if(p[u->piece].value != LVAL && p[u->epVictim[0]].value == LVAL) deferred |= PROMOTE; // flag non-Lion x Lion\r
     cnt50 = 0; // double capture irreversible\r
   }\r
 \r
@@ -1453,7 +1460,7 @@ MakeMove(Move m, UndoInfo *u)
     u->booty -= p[u->piece].value;\r
     cnt50 = 0;\r
   } else\r
-  if(p[u->piece].value == 10*FVAL) { // move with Fire Demon that survives: burn\r
+  if(p[u->piece].value == FVAL) { // move with Fire Demon that survives: burn\r
     int i, f=fireFlags[u->piece-2];\r
     for(i=0; i<8; i++) {\r
        int x = u->to + kStep[i], burnVictim = board[x];\r
@@ -1521,7 +1528,7 @@ UnMake(UndoInfo *u)
     }\r
   }\r
 \r
-  if(p[u->piece].value == 10*FVAL) {\r
+  if(p[u->piece].value == FVAL) {\r
     int i, f=fireFlags[u->piece-2];\r
     for(i=0; i<8; i++) fireBoard[u->from + kStep[i]] |= f; // restore old burn zone\r
   }\r
@@ -1664,19 +1671,95 @@ GenCapts(int sqr, int victimValue)
 }\r
 \r
 int\r
+Guard (int sqr)\r
+{\r
+  int piece = board[sqr], val;\r
+  if(piece == EDGE) return 0;\r
+  val = p[piece].value;\r
+  if(val == 201) return 3; // Elephant\r
+  if(val == 152) return 2; // Tiger\r
+  if(val == 151) return 1; // Gold\r
+  return 0;\r
+}\r
+\r
+int\r
+Fortress (int forward, int king, int lion)\r
+{ // penalty for lack of Lion-proof fortress\r
+  int rank = PST[king], anchor, r, l, q;\r
+  if(!rank) return -300;\r
+  anchor = king + forward*(rank-1);\r
+\r
+  if(Guard(anchor) == 3 || Guard(anchor+1) == 3 || Guard(anchor-1) == 3) return 0;\r
+  if(rank == 2 && Guard(king+1) == 3 || Guard(king-1) == 3) return -50;\r
+  if(Guard(r=anchor) == 2 || Guard(r=anchor+1) == 2 || Guard(r=anchor-1) == 2)\r
+    return -100 + 50*(Guard(r + forward + 1) == 3 || Guard(r + forward - 1) == 3);\r
+  return -300;\r
+\r
+  for(r=anchor+1; Guard(r) > 1; r++);\r
+  for(l=anchor-1; Guard(l) > 1; l--);\r
+//if(PATH) printf("# l=%d r=%d\n", l, r);\r
+  if(Guard(anchor) < 2) {\r
+    if(r - anchor  > anchor - l || // largest group, or if equal, group that contains elephant\r
+       r - anchor == anchor - l && Guard(r-1) == 3) l = anchor; else r = anchor;\r
+  }\r
+  switch(r - l) {\r
+    case 1: q = 15; break;                // no shelter at all, maximum penalty\r
+    case 2: if(Guard(l+1) == 3) q = 10;   // single Elephant offers some shelter\r
+           else if(Guard(l+forward) == 3 || Guard(l+forward+2) == 3) q = 8; // better if Tiger diagonally in front of it\r
+           else q = 14;                  // singe tiger almost no help;\r
+           break;\r
+    case 3: q = 5 - (Guard(l+1) == 3 || Guard(l+3) == 3); break; // pair is better if it contains Elephant\r
+    case 4: q = (Guard(l+2) != 3);        // 3 wide: perfect, or nearly so if Elephant not in middle\r
+    default: ;\r
+  }\r
+//if(PATH) printf("# fortress %d: q=%d l=%d r=%d\n", anchor, q, l, r);\r
+  return (dist[lion - king] - 23)*q;      // reduce by ~half if Lion very far away\r
+}\r
+\r
+int\r
+Ftest (int side)\r
+{\r
+  int lion = ABSENT, king;\r
+  if(p[side+2].value == LVAL) lion = p[side+2].pos;\r
+  if(lion == ABSENT && p[side+4].value == LVAL) lion = p[side+4].pos;\r
+  king = p[royal[1-side]].pos; if(king == ABSENT) king = p[royal[1-side]+1].pos;\r
+  return lion == ABSENT ? 0 : Fortress(side ? -BW : BW, king, lion);\r
+}\r
+\r
+int\r
 Evaluate (int difEval)\r
 {\r
-  int wLion, bLion, wKing, bKing, score=mobilityScore;\r
+  int wLion = ABSENT, bLion = ABSENT, wKing, bKing, score=mobilityScore, f, i, j;\r
+\r
+  if(p[WHITE+2].value == LVAL) wLion = p[WHITE+2].pos;\r
+  if(p[BLACK+2].value == LVAL) bLion = p[BLACK+2].pos;\r
+  if(wLion == ABSENT && p[WHITE+4].value == LVAL) wLion = p[WHITE+4].pos;\r
+  if(bLion == ABSENT && p[BLACK+4].value == LVAL) bLion = p[BLACK+4].pos;\r
 \r
 #ifdef LIONTRAP\r
-#define lionTrap (PST + 2*BH*BW)\r
+# define lionTrap (PST + 2*BH*BW)\r
   // penalty for Lion in enemy corner, when enemy Lion is nearby\r
-  if(p[WHITE+2].value == 10*LVAL && (wLion = p[WHITE+2].pos) != ABSENT)\r
-    if(p[BLACK+2].value == 10*LVAL && (bLion = p[BLACK+2].pos) != ABSENT) { // both have a Lion\r
+  if(wLion != ABSENT && bLion != ABSENT) { // both have a Lion\r
       static int distFac[36] = { 0, 0, 10, 9, 8, 7, 5, 3, 1 };\r
       score -= ( (1+9*!attacks[2*wLion+WHITE]) * lionTrap[BW*(BH-1)+BH-1-wLion]\r
                - (1+9*!attacks[2*bLion+BLACK]) * lionTrap[bLion] ) * distFac[dist[wLion - bLion]];\r
   }\r
+\r
+# ifdef WINGS\r
+  // bonus if corner lances are protected by Lion-proof setup (FL + C/S)\r
+  if(bLion != ABSENT) {\r
+    if((p[board[BW+lr]].value == 320 || p[board[BW+lr]].value == 220) && \r
+        p[board[ll+1]].value == 150 && p[board[ll+BW+2]].value == 100) score += 20 + 20*!p[board[ll]].range[2];\r
+    if((p[board[BW+lr]].value == 320 || p[board[BW+lr]].value == 220) &&\r
+        p[board[lr-1]].value == 150 && p[board[lr+BW-2]].value == 100) score += 20 + 20*!p[board[lr]].range[2];\r
+  }\r
+  if(wLion != ABSENT) {\r
+    if((p[board[ul-BW]].value == 320 || p[board[ul-BW]].value == 220) &&\r
+        p[board[ul+1]].value == 150 && p[board[ul-BW+2]].value == 100) score -= 20 + 20*!p[board[ul]].range[2];\r
+    if((p[board[ur-BW]].value == 320 || p[board[ur-BW]].value == 220) &&\r
+        p[board[ur-1]].value == 150 && p[board[ur-BW-2]].value == 100) score -= 20 + 20*!p[board[ur]].range[2];\r
+  }\r
+# endif\r
 #endif\r
 \r
 #ifdef KINGSAFETY\r
@@ -1684,8 +1767,18 @@ Evaluate (int difEval)
   wKing = p[royal[WHITE]].pos; if(wKing == ABSENT) wKing = p[royal[WHITE]+1].pos;\r
   bKing = p[royal[BLACK]].pos; if(bKing == ABSENT) bKing = p[royal[BLACK]+1].pos;\r
   if(filling < 32) {\r
-    score += (PST[3*BW*BH+wKing] - PST[3*BW*BH+bKing])*(32 - filling) >> 4;\r
+    int lead = (stm == WHITE ? difEval : -difEval);\r
+    score += (PST[3*BW*BH+wKing] - PST[3*BW*BH+bKing])*(32 - filling) >> 7;\r
+    if(lead  > 100) score -= PST[3*BW*BH+bKing]*(32 - filling) >> 3; // white leads, drive black K to corner\r
+    if(lead < -100) score += PST[3*BW*BH+wKing]*(32 - filling) >> 3; // black leads, drive white K to corner\r
   }\r
+\r
+# ifdef FORTRESS\r
+  f = 0;\r
+  if(bLion != ABSENT) f += Fortress( BW, wKing, bLion);\r
+  if(wLion != ABSENT) f -= Fortress(-BW, bKing, wLion);\r
+  score += (filling < 96 ? f : f*(224 - filling) >> 7); // build up slowly\r
+# endif\r
 #endif\r
 \r
 #ifdef KYLIN\r
@@ -1698,6 +1791,18 @@ Evaluate (int difEval)
   }\r
 #endif\r
 \r
+#ifdef PAWNBLOCK\r
+  // penalty for blocking own P or GB: 20 by slider, 10 by other, but 50 if only retreat mode is straight back\r
+  for(i=last[WHITE]; i > 1 && p[i].value<=50; i-=2) {\r
+    if((f = p[i].pos) != ABSENT && (j = board[f + BW])&1) // P present, square before it white (odd) piece\r
+      score -= 10 + 10*(p[j].promoGain > 0) + 30*!(p[j].range[3] || p[j].range[5] || p[j].value==50);\r
+  }\r
+  for(i=last[BLACK]; i > 1 && p[i].value<=50; i-=2) {\r
+    if((f = p[i].pos) != ABSENT && (j = board[f - BW]) && !(j&1)) // P present, square before non-empty and even (black)\r
+      score += 10 + 10*(p[j].promoGain > 0) + 30*!(p[j].range[1] || p[j].range[7] || p[j].value==50);\r
+  }\r
+#endif\r
+\r
   return difEval - (filling*filling*promoDelta >> 16) + (stm ? score : -score);\r
 }\r
 \r
@@ -1705,7 +1810,7 @@ inline void
 FireSet (UndoInfo *tb)\r
 { // set fireFlags acording to remaining presene of Fire Demons\r
   int i;\r
-  for(i=stm+2; p[i].value == 10*FVAL; i++) // Fire Demons are always leading pieces in list\r
+  for(i=stm+2; p[i].value == FVAL; i++) // Fire Demons are always leading pieces in list\r
     if(p[i].pos != ABSENT) tb->fireMask |= fireFlags[i-2];\r
 }\r
 \r
@@ -1714,9 +1819,9 @@ void TerminationCheck();
 #define QSdepth 4\r
 \r
 int\r
-Search (int alpha, int beta, int difEval, int depth, int oldPromo, int promoSuppress, int threshold)\r
+Search (int alpha, int beta, int difEval, int depth, int lmr, int oldPromo, int promoSuppress, int threshold)\r
 {\r
-  int i, j, k, phase, king, nextVictim, to, defer, autoFail=0, inCheck = 0, late=INF;\r
+  int i, j, k, phase, king, nextVictim, to, defer, autoFail=0, inCheck = 0, late=100000;\r
   int firstMove, oldMSP = msp, curMove, sorted, bad, dubious, bestMoveNr;\r
   int resDep, iterDep, ext;\r
   int myPV = pvPtr;\r
@@ -1742,11 +1847,12 @@ if(PATH) /*pboard(board),pmap(attacks, BLACK),*/printf("search(%d) {%d,%d} eval=
         }\r
       }\r
 #ifdef CHECKEXT\r
-      else if(depth >= QSdepth) inCheck = 1, depth++;\r
+      else { inCheck = 1; if(depth >= QSdepth) depth++; }\r
 #endif\r
     }\r
   }\r
 \r
+if(!level) {for(i=0; i<5; i++)printf("# %d %08x, %d\n", i, repStack[200-i], checkStack[200-i]);}\r
   // KING CAPTURE\r
   k = p[king=royal[xstm]].pos;\r
   if( k != ABSENT) {\r
@@ -1759,13 +1865,13 @@ if(PATH) /*pboard(board),pmap(attacks, BLACK),*/printf("search(%d) {%d,%d} eval=
   }\r
 //printf("King safe\n");fflush(stdout);\r
   // EVALUATION & WINDOW SHIFT\r
-  curEval = Evaluate(difEval);\r
+  curEval = Evaluate(difEval) -20*inCheck;\r
   alpha -= (alpha < curEval);\r
   beta  -= (beta <= curEval);\r
 \r
   if(!(nodes++ & 4095)) TerminationCheck();\r
   pv[pvPtr++] = 0; // start empty PV, directly behind PV of parent\r
-\r
+  if(inCheck) lmr = 0; else depth -= lmr; // no LMR of checking moves\r
 \r
   firstMove = curMove = sorted = msp += 50; // leave 50 empty slots in front of move list\r
   iterDep = -(depth == 0); tb.fireMask = phase = 0;\r
@@ -1784,6 +1890,7 @@ if(PATH) printf("# probe hash index=%x hit=%d\n", index, hit),fflush(stdout);
        (bestScore >= beta  || hashTable[index].flag[hit] & H_UPPER)   ) {\r
       iterDep = resDep = hashTable[index].depth[hit]; bestMoveNr = 0;\r
       if(!level) iterDep = 0; // no hash cutoff in root\r
+      if(lmr && bestScore <= alpha && iterDep == depth) depth ++, lmr--; // self-deepening LMR\r
       if(pvCuts && iterDep >= depth && hashMove && bestScore < beta && bestScore > alpha)\r
        iterDep = depth - 1; // prevent hash cut in PV node\r
     }\r
@@ -1818,12 +1925,13 @@ if(PATH)printf("new moves, phase=%d\n", phase);
        switch(phase) {\r
          case 0: // null move\r
 #ifdef NULLMOVE\r
-           if(depth > QSdepth && curEval >= beta && !inCheck) {\r
+           if(depth > QSdepth && curEval >= beta && !inCheck && filling > 10) {\r
               int nullDep = depth - 3;\r
              stm ^= WHITE;\r
-             score = -Search(-beta, 1-beta, -difEval, nullDep<QSdepth ? QSdepth : nullDep, promoSuppress & SQUARE, ABSENT, INF);\r
+             score = -Search(-beta, 1-beta, -difEval, nullDep<QSdepth ? QSdepth : nullDep, 0, promoSuppress & SQUARE, ABSENT, INF);\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
            }\r
 #endif\r
            if(tenFlag) FireSet(&tb); // in tenjiku we must identify opposing Fire Demons to perform any moves\r
@@ -1903,8 +2011,10 @@ if(PATH) printf("# autofail end (%d-%d)\n", firstMove, msp);
          case 7: // bad captures\r
          case 8: // PV null move\r
            phase = 9;\r
+if(PATH) printf("# null = %0x\n", nullMove);\r
            if(nullMove != ABSENT) {\r
              moveStack[msp++] = nullMove + (nullMove << SQLEN) | DEFER; // kludge: setting DEFER guarantees != 0, and has no effect\r
+             break;\r
            }\r
 //printf("# %d. sqr = %08x null = %08x\n", msp, nullMove, moveStack[msp-1]);\r
          case 9:\r
@@ -1948,9 +2058,16 @@ if(flag & depth >= 0) printf("%2d:%d found %d/%d %08x %s\n", depth, iterDep, cur
 if(flag & depth >= 0) printf("%2d:%d made %d/%d %s\n", depth, iterDep, curMove, msp, MoveToText(moveStack[curMove], 0));\r
       for(i=2; i<=cnt50; i+=2) if(repStack[level-i+200] == hashKeyH) {\r
        if(repDraws) { score = 0; goto repetition; }\r
-       moveStack[curMove] = 0; // erase forbidden move\r
-       if(!level) repeatMove[repCnt++] = move & 0xFFFFFF; // remember outlawed move\r
-       score = -INF; moveStack[curMove] = 0; goto repetition;\r
+       if(!allowRep) {\r
+         moveStack[curMove] = 0;         // erase forbidden move\r
+         if(!level) repeatMove[repCnt++] = move & 0xFFFFFF; // remember outlawed move\r
+       } else { // check for perpetuals\r
+//       int repKey = 1;\r
+//       for(i-=level; i>1; i-=2) {repKey &= checkStack[200-i]; if(!level)printf("# repkey[%d] = %d\n", 200-i, repKey);}\r
+         if(inCheck) { score = INF-20; goto repetition; } // we might be subject to perpetual check: score as win\r
+         if(i == 2 && repStack[level+199] == hashKeyH) { score = INF-20; goto repetition; } // consecutive passing\r
+       }\r
+       score = -INF + 8*allowRep; goto repetition;\r
       }\r
       repStack[level+200] = hashKeyH;\r
 \r
@@ -1960,9 +2077,9 @@ attacks += 2*bsize;
 MapFromScratch(attacks); // for as long as incremental update does not work.\r
 //if(flag & depth >= 0) printf("%2d:%d mapped %d/%d %s\n", depth, iterDep, curMove, msp, MoveToText(moveStack[curMove], 0));\r
 //if(PATH) pmap(attacks, stm);\r
-      if(chuFlag && p[tb.victim].value == 10*LVAL) {// verify legality of Lion capture in Chu Shogi\r
+      if(chuFlag && p[tb.victim].value == LVAL) {// verify legality of Lion capture in Chu Shogi\r
        score = 0;\r
-       if(p[tb.piece].value == 10*LVAL) {          // Ln x Ln: can make Ln 'vulnerable' (if distant and not through intemediate > GB)\r
+       if(p[tb.piece].value == LVAL) {          // Ln x Ln: can make Ln 'vulnerable' (if distant and not through intemediate > GB)\r
          if(dist[tb.from-tb.to] != 1 && attacks[2*tb.to + stm] && p[tb.epVictim[0]].value <= 50)\r
            score = -INF;                           // our Lion is indeed made vulnerable and can be recaptured\r
        } else {                                    // other x Ln\r
@@ -1970,13 +2087,15 @@ MapFromScratch(attacks); // for as long as incremental update does not work.
          defer |= PROMOTE;                         // if we started, flag  he cannot do it in reply\r
        }\r
         if(score == -INF) {\r
-          if(level == 1) repeatMove[repCnt++] = move & 0xFFFFFF | (p[tb.piece].value == 10*LVAL ? 3<<24 : 1 << 24);\r
+          if(level == 1) repeatMove[repCnt++] = move & 0xFFFFFF | (p[tb.piece].value == LVAL ? 3<<24 : 1 << 24);\r
           moveStack[curMove] = 0; // zap illegal moves\r
           goto abortMove;\r
         }\r
       }\r
 #if 1\r
-      score = -Search(-beta, -iterAlpha, -difEval - tb.booty, iterDep-1+ext, promoSuppress & ~PROMOTE, defer, depth ? INF : tb.gain);\r
+      score = -Search(-beta, -iterAlpha, -difEval - tb.booty, iterDep-1+ext,\r
+                       curMove >= late && iterDep > QSdepth + LMR,\r
+                                                      promoSuppress & ~PROMOTE, defer, depth ? INF : tb.gain);\r
 #else\r
       score = 0;\r
 #endif\r
@@ -2039,13 +2158,17 @@ if(PATH) printf("%d:%2d:%d %3d %6x %-10s %6d %6d  (%d)\n", level, depth, iterDep
        printf("%d %d %d %d", iterDep-QSdepth, bestScore, lastRootIter/10, nodes);\r
         if(ponderMove) printf(" (%s)", MoveToText(ponderMove, 0));\r
        for(i=0; pv[i]; i++) printf(" %s", MoveToText(pv[i], 0));\r
-        if(iterDep == QSdepth+1) printf(" { root eval = %4.2f dif = %4.2f; abs = %4.2f f=%d D=%4.2f/%4.2f}", curEval/100., difEval/100., PSTest()/100., filling, promoDelta/100., Dtest()/100.);\r
+        if(iterDep == QSdepth+1) printf(" { root eval = %4.2f dif = %4.2f; abs = %4.2f f=%d D=%4.2f %d/%d}", curEval/100., difEval/100., PSTest()/100., filling, promoDelta/100., Ftest(0), Ftest(1));\r
        printf("\n");\r
         fflush(stdout);\r
       }\r
       if(!(abortFlag & 1) && GetTickCount() - startTime > tlim1) break; // do not start iteration we can (most likely) not finish\r
     }\r
     if(resDep > iterDep) iterDep = resDep; // skip iterations if we got them for free\r
+#ifdef LMR\r
+    if(lmr && bestScore <= alpha && iterDep == depth)\r
+      depth++, lmr--; // self-deepen on fail-low reply to late move by lowering reduction\r
+#endif\r
 #ifdef HASH\r
     // hash store\r
     hashTable[index].lock[hit]  = hashKeyH;\r
@@ -2064,7 +2187,7 @@ leave:
   msp = oldMSP; // pop move list\r
   pvPtr = myPV; // pop PV\r
   retMove = bestMoveNr ? moveStack[bestMoveNr] : 0;\r
-  retDep = resDep - inCheck;\r
+  retDep = resDep - (inCheck & depth >= QSdepth) + lmr;\r
 if(PATH) printf("return %d: %d %d (t=%d s=%d lim=%d)\n", depth, bestScore, curEval, GetTickCount(), startTime, tlim1),fflush(stdout);\r
   return bestScore + (bestScore < curEval);\r
 }\r
@@ -2166,16 +2289,29 @@ int sup0, sup1, sup2; // promo suppression squares
 int lastLift, lastPut;\r
 \r
 int\r
+InCheck ()\r
+{\r
+  int k = p[royal[stm]].pos;\r
+  if( k == ABSENT) k = p[royal[stm] + 2].pos;\r
+  else if(p[royal[stm] + 2].pos != ABSENT) k = ABSENT; // two kings is no king...\r
+  if( k != ABSENT) {\r
+    MapFromScratch(attacks);\r
+    if(attacks[2*k + 1 - stm]) return 1;\r
+  }\r
+  return 0;\r
+}\r
+\r
+int\r
 MakeMove2 (int stm, MOVE move)\r
 {\r
-  int i;\r
+  int i, inCheck = InCheck();\r
   FireSet(&undoInfo);\r
   sup0 = sup1; sup1 = sup2;\r
   sup2 = MakeMove(move, &undoInfo);\r
-  if(chuFlag && p[undoInfo.victim].value == 10*LVAL && p[undoInfo.piece].value != 10*LVAL) sup2 |= PROMOTE;\r
+  if(chuFlag && p[undoInfo.victim].value == LVAL && p[undoInfo.piece].value != LVAL) sup2 |= PROMOTE;\r
   rootEval = -rootEval - undoInfo.booty;\r
-  for(i=0; i<200; i++) repStack[i] = repStack[i+1];\r
-  repStack[199] = hashKeyH;\r
+  for(i=0; i<200; i++) repStack[i] = repStack[i+1], checkStack[i] = checkStack[i+1];\r
+  repStack[199] = hashKeyH, checkStack[199] = inCheck;\r
 printf("# makemove %08x %c%d %c%d\n", move, sup1%BW+'a', sup1/BW, sup2%BW+'a', sup2/BW);\r
   return stm ^ WHITE;\r
 }\r
@@ -2186,7 +2322,7 @@ UnMake2 (MOVE move)
   int i;\r
   rootEval = -rootEval - undoInfo.booty;\r
   UnMake(&undoInfo);\r
-  for(i=200; i>0; i--) repStack[i] = repStack[i-1];\r
+  for(i=200; i>0; i--) repStack[i] = repStack[i-1], checkStack[i] = checkStack[i-1];\r
   sup2 = sup1; sup1 = sup0;\r
 }\r
 \r
@@ -2307,7 +2443,7 @@ ListMoves ()
   for(i=0; i< BSIZE; i++) boardCopy[i] = !!board[i];\r
 MapFromScratch(attacks);\r
   postThinking--; repCnt = 0; tlim1 = tlim2 = tlim3 = 1e8; abortFlag = msp = 0;\r
-  Search(-INF-1, INF+1, 0, QSdepth+1, sup1 & ~PROMOTE, sup2, INF);\r
+  Search(-INF-1, INF+1, 0, QSdepth+1, 0, sup1 & ~PROMOTE, sup2, INF);\r
   postThinking++;\r
   listStart = retFirst; listEnd = msp = retMSP;\r
 }\r
@@ -2429,9 +2565,9 @@ SetSearchTimes (int timeLeft)
   if(mps) movesLeft = mps - (moveNr>>1)%mps;\r
   targetTime = (timeLeft - 1000*inc) / (movesLeft + 2) + 1000 * inc;\r
   if(moveNr < 30) targetTime *= 0.5 + moveNr/60.; // speedup in opening\r
-  if(timePerMove > 0) targetTime = 0.5*timeLeft, movesLeft = 1;\r
-  tlim1 = 0.2*targetTime;\r
-  tlim2 = 1.9*targetTime;\r
+  if(timePerMove > 0) targetTime = 0.4*timeLeft, movesLeft = 1;\r
+  tlim1 = 0.4*targetTime;\r
+  tlim2 = 2.4*targetTime;\r
   tlim3 = 5*timeLeft / (movesLeft + 4.1);\r
 printf("# limits %d, %d, %d mode = %d\n", tlim1, tlim2, tlim3, abortFlag);\r
 }\r
@@ -2439,14 +2575,14 @@ printf("# limits %d, %d, %d mode = %d\n", tlim1, tlim2, tlim3, abortFlag);
 int\r
 SearchBestMove (MOVE *move, MOVE *ponderMove)\r
 {\r
-  int score;\r
+  int score, i;\r
 printf("# SearchBestMove\n");\r
   startTime = GetTickCount();\r
   nodes = 0;\r
 printf("# s=%d\n", startTime);fflush(stdout);\r
 MapFromScratch(attacks);\r
   retMove = INVALID; repCnt = 0;\r
-  score = Search(-INF-1, INF+1, rootEval, maxDepth, sup1, sup2, INF);\r
+  score = Search(-INF-1, INF+1, rootEval, maxDepth, 0, sup1, sup2, INF);\r
   *move = retMove;\r
   *ponderMove = pv[1];\r
 printf("# best=%s\n", MoveToText(pv[0],0));\r
@@ -2489,6 +2625,7 @@ printf("# in (mode = %d,%d): %s\n", root, abortFlag, command);
         if(!strcmp(command, "time"))    { sscanf(inBuf, "time %d", &timeLeft); continue; }\r
         if(!strcmp(command, "put"))     { ReadSquare(inBuf+4, &lastPut); continue; }  // ditto\r
         if(!strcmp(command, "."))       { inBuf[0] = 0; return; } // ignore for now\r
+        if(!strcmp(command, "hover"))   { inBuf[0] = 0; return; } // ignore for now\r
         if(!strcmp(command, "lift"))    { inBuf[0] = 0; Highlight(inBuf+5); return; } // treat here\r
         if(!root && !strcmp(command, "usermove")) {\r
 printf("# move = %s#ponder = %s", inBuf+9, ponderMoveText);\r
@@ -2523,7 +2660,7 @@ printf("# ponder hit\n");
       int i, score, curVarNr;\r
 \r
   Init(V_CHU); // Chu\r
-      seed = GetTickCount(); moveNr = 0; // initialize random\r
+      seed = startTime = GetTickCount(); moveNr = 0; // initialize random\r
 \r
       while(1) { // infinite loop\r
 \r
@@ -2604,20 +2741,24 @@ pboard(board);
           printf("feature variants=\"normal,shatranj,makruk,chu,dai,tenjiku,12x12+0_fairy,9x9+0_shogi\"\n");\r
           printf("feature myname=\"HaChu " VERSION "\" highlight=1\n");\r
           printf("feature option=\"Full analysis PV -check 1\"\n"); // example of an engine-defined option\r
+          printf("feature option=\"Allow repeats -check 0\"\n");\r
+          printf("feature option=\"Promote on entry -check 0\"\n");\r
           printf("feature option=\"Resign -check 0\"\n");           // \r
           printf("feature option=\"Contempt -spin 0 -200 200\"\n"); // and another one\r
-          printf("feature option=\"Tsume -combo no /// White Mates /// Black mates\"\n");\r
+          printf("feature option=\"Tsume -combo no /// Sente mates /// Gote mates\"\n");\r
           printf("feature done=1\n");\r
           continue;\r
         }\r
         if(!strcmp(command, "option")) { // setting of engine-define option; find out which\r
           if(sscanf(inBuf+7, "Full analysis PV=%d", &noCut)  == 1) continue;\r
+          if(sscanf(inBuf+7, "Allow repeats=%d", &allowRep)  == 1) continue;\r
           if(sscanf(inBuf+7, "Resign=%d",   &resign)         == 1) continue;\r
           if(sscanf(inBuf+7, "Contempt=%d", &contemptFactor) == 1) continue;\r
+          if(sscanf(inBuf+7, "Promote on entry=%d", &entryProm) == 1) continue;\r
           if(sscanf(inBuf+7, "Tsume=%s", command) == 1) {\r
            if(!strcmp(command, "no"))    tsume = 0; else\r
-           if(!strcmp(command, "White")) tsume = 1; else\r
-           if(!strcmp(command, "Black")) tsume = 2;\r
+           if(!strcmp(command, "Sente")) tsume = 1; else\r
+           if(!strcmp(command, "Gote"))  tsume = 2;\r
            continue;\r
          }\r
           continue;\r
@@ -2648,7 +2789,7 @@ pboard(board);
         if(!strcmp(command, "ics"))     { continue; }\r
         if(!strcmp(command, "accepted")){ continue; }\r
         if(!strcmp(command, "rejected")){ continue; }\r
-        if(!strcmp(command, "result"))  { continue; }\r
+        if(!strcmp(command, "result"))  { engineSide = NONE; continue; }\r
         if(!strcmp(command, "hover"))   { continue; }\r
         if(!strcmp(command, ""))  {  continue; }\r
         if(!strcmp(command, "usermove")){\r
@@ -2677,6 +2818,7 @@ pboard(board);
               Init(curVarNr = i); stm = Setup2(NULL); break;\r
             }\r
          }\r
+         repStack[199] = hashKeyH, checkStack[199] = 0;\r
           continue;\r
         }\r
         if(!strcmp(command, "setboard")){ engineSide = NONE;  Init(curVarNr); stm = Setup2(inBuf+9); continue; }\r