From ce081b5204aa8e7deea2cc321277c77e11a1a88b Mon Sep 17 00:00:00 2001 From: H.G.Muller Date: Tue, 10 Apr 2018 19:25:24 +0200 Subject: [PATCH] Implement Kyoto Shogi Previous commits have created all infra-structure needed to handle Kyoto Shogi. This patch adds Kyoto Shogi to the list of variants, plus the required info (setup FEN, piece IDs and moves, pieceToCharTable). The strongest member of each alternating pair is defined as the promoted piece, so that P, L and N will be subjected to the drop restrictions (applied only to unpromoted pieces). As usual P and L will be piece 0 and 1, while N will be the last unpromoted piece. A compacted version of the piece-square data is included as initialized data, as the non-ergodic pieces require very unusual and specific tables. This data is used to create a separate PST for each piece type. (Two 5x5 tables packed into one normal 11x11 space to not exceed the normal number of tables.) The (common) promoGain of all hand pieces had to be set to a non-zero value in order to prevent overflow in the had PST, as the difference between hand value and value of the unpromoted piece is unusually large (as promoted dropping is possible). --- dropper.c | 52 +++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 45 insertions(+), 7 deletions(-) diff --git a/dropper.c b/dropper.c index 6ec2a14..8bfb7e4 100644 --- a/dropper.c +++ b/dropper.c @@ -300,6 +300,7 @@ shogiValues[] = { 30, 150, 240, 270, 390, 450, 180, 200, -1, 330, 288, 276, 27 miniValues[] = { 60, 110, 195, 237, 243, 330, -1, 297, 245, 240, 237, 375, 420, -1, 120, 200, 243, 252, 315, 390, -1 }, judkinValues[] = { 50, 115, 240, 270, 325, 390, 180, -1, 330, 245, 276, 270, 420, 480, 282, -1, 60, 220, 300, 330, 450, 510, 285, -1 }, toriValues[] = { 60, 100, 150, 150, 237, 300, -1, 90, 0, 0, 0, 0, 0, 500, -1, 65, 150, 200, 200, 300, 400, -1 }, +kyotoValues[] = { 115, 117, 304, 100, -1, 275, 198, 346, 172, -1, 360, 317, 378, 301, -1 }, waValues[] = { 30, 210, 210, 180, 210, 210, 210, 240, 270, 160, 175, 270, 300, 360, 540, 480, -1, 330, 360, 480, 360, 240, 270, 270, 300, 330, 330, 270, 360, 540, 540, -1, 60, 240, 300, 270, 255, 270, 240, 285, 330, 270, 285, 345, 480, 480, 630, 480, -1 }; @@ -310,6 +311,7 @@ shogiDirs[] = { 40, 69, 97, 87, 57, 35, 26, 186, 227, 255, 57, 57, 57, 57, 31, 2 40, 62, 94, 43, 64, 35, 26, 10, 232, 255, 64, 64, 64, 64, 31, 22, 64, 57, 255 }, toriDirs[] = { 40, 69, 189, 197, 201, 42, 79, 255, 112, 0, 0, 0, 0, 168, 255, // Ph, S, Pt, Ql, Qr, Cr, Fa / G - - - - Ea 40, 62, 193, 205, 209, 42, 71, 255, 108, 0, 0, 0, 0, 177, 255 }, +kyotoDirs[] = { 40, 69, 97, 87, 186, 255, 26, 57, 35, 57, 255, 40, 62, 94, 43, 10, 255, 26, 64, 35, 64, 255 }, // K,P,L,S,N / R,T,B,G waDirs[] = { 40, 69, 97, 67, 67, 74, 59, 59, 73, 87, 57, 96, 116, 121, 135, 99, 150, 255, // CK,SP,SC,SO,FC,CM,FG,BD,VS,VW,OC,LH,SW,RR,FF,Tr,CE 57, 40,135,150,213, 87,116, 57, 79, 40, 8, 26, 99, 141, 255, // GB,FF,CE,RF,VS,SW,VW,RB,BE,PO,HH,GS,Tr,TF 40, 62, 94, 60, 60, 82, 66, 66, 81, 43, 64, 93, 116, 128, 34, 99, 159, 255, @@ -320,6 +322,7 @@ chessIDs[] = "PNBRQ", shogiIDs[] = "PLSGBRN", euroIDs[] = "PLSGBR?N", toriIDs[] = "SPLRCF", +kyotoIDs[] = "PLSN............RTBG", // R, T, B, G are synonyms for +P, +L, +S and +N (written and recognized in drop moves) waIDs[] = "POULCMGDVWHSRFXE", chessFEN[] = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -", @@ -329,6 +332,7 @@ waFEN[] = "hmlcvkwgudo/1e3s3f1/ppprpppxppp/3p3p3/11/11/11/3P3P3/PPPXPPPRPPP/1 miniFEN[] = "rbsgk/4p/5/P4/KGSBR w", judkinFEN[]= "rbnsgk/5p/6/6/P5/KGSNBR w", euroFEN[] = "1nbgkgn1/1r4b1/pppppppp/8/8/PPPPPPPP/1B4R1/1NGKGBN1 w", +kyotoFEN[] = "pgkst/5/5/5/TSKGP w", // promotion codes for unpromoted pieces. Will be ANDed with Z_WHITE or Z_BLACK to fill promoCode[] table @@ -342,12 +346,14 @@ euroFEN[] = "1nbgkgn1/1r4b1/pppppppp/8/8/PPPPPPPP/1B4R1/1NGKGBN1 w", chessProms[16] = { Z_MUST }, shogiProms[16] = { Z_MUST, Z_2ND, COLOR, 0, Z_MUST, Z_MUST, Z_2ND, Z_2ND }, toriProms[16] = { Z_MUST, 0, 0, 0, 0, Z_MUST }, +kyotoProms[16] = { Z_MUST, Z_MUST, Z_MUST, 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, 1, 3, 3, 1 }; // bitmap indicating piece types with drop restriction (LSB = Pawn) in various variants +int lances[] = { 1, 013, 3, 0103, 0103, 1, 3, 3, 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 + NULL, "", "", NULL, @@ -360,6 +366,7 @@ char *betza[] = { // piece defs for sending to GUI char *ptc[] = { // XBoard 4.9 piece-to-char table NULL, + NULL, "P.BR.S...G.+.++.+Kp.br.s...g.+.++.+k", "PNBR.S...G.++++.+Kpnbr.s...g.++++.+k", NULL, @@ -372,6 +379,7 @@ char *ptc[] = { // XBoard 4.9 piece-to-char table char *pstType[] = { "", + "", "307716 777718", "3077160 7777187", "3077160 7777187", @@ -391,6 +399,7 @@ typedef struct { VariantDesc variants[] = { { 8, 8, 5, 1, "crazyhouse\n", chessIDs, chessFEN, chessDirs, chessProms, chessCodes, chessValues }, + { 5, 5, 4, 5, "kyotoshogi\n", kyotoIDs, kyotoFEN, kyotoDirs, kyotoProms, shogiCodes, kyotoValues }, { 5, 5, 5, 1, "minishogi\n", shogiIDs, miniFEN, shogiDirs, shogiProms, shogiCodes, miniValues }, { 6, 6, 6, 2, "judkinshogi\n", shogiIDs, judkinFEN, shogiDirs, shogiProms, shogiCodes, judkinValues }, { 9, 9, 7, 3, "shogi\n", shogiIDs, shogiFEN, shogiDirs, shogiProms, shogiCodes, shogiValues }, @@ -400,9 +409,10 @@ VariantDesc variants[] = { { 7, 7, 6, 2, "torishogi\n", toriIDs, toriFEN, toriDirs, toriProms, toriCodes, toriValues }, }; -#define TORI_NR 7 /* must correspond to index of torishogi (which must be last) in table above! */ -#define MINI_NR 1 -#define KNIGHTLESS 4 /* first variant without a Knight (except mini-, which has no 2-rank zone) */ +#define TORI_NR 8 /* must correspond to index of torishogi (which must be last) in table above! */ +#define KYOTO_NR 1 +#define MINI_NR 2 +#define KNIGHTLESS 5 /* first variant without a Knight (except mini-, which has no 2-rank zone) */ // info per piece type. sometimes indexed by negated holdings count instead of piece #define pieceKey (rawKey+1) @@ -424,6 +434,17 @@ unsigned int squareKey[22*11]; signed char pstData[22*11*9]; // actual tables (for now 9 pairs) +signed char kyotoPST[8][15] = { // 3 values per rank (a-c file) + { -114,-114,-114, 48, 59, 62, 82, 97,102, 95, 110, 115, 95, 110, 115 }, // P-R + { -117,-117,-117, -31, -15, -15, 17, 46, 46, 52, 86, 88, 79, 115, 118 }, // L-T + { -64, -45, -32, -19, 48, 50, -10, 54, 65, -14, 56, 62, -46, -6, 4 }, // S-B + { -100,-100,-100, -100,-100,-100, -10, 11, 21, 53, 67, 85, 69, 83, 101 }, // N-G + { -55, -37, -31, 2, 26, 33, 22, 47, 55, 23, 48, 56, 6, 30, 38 }, // R-P + { -107, -80, -80, -33, 30, 31, 9, 74, 98, 35, 101, 108, 20, 84, 92 }, // T-L + { -57, -49, -40, -51, 0, 9, -39, 14, 58, -49, 4, 17, -57, -46, -37 }, // B-S + { -107, -75, -75, -30, 31, 32, -3, 58, 81, 37, 105, 108, 25, 93, 95 }, // G-N +}; + int MyRandom () { @@ -551,7 +572,7 @@ GameInit (char *name) PST[WHITE+4] = PST[BLACK+4] = kingPST+11; // Queens frontier = 2*22; killZone = 3*22; impasse = boardEnd; } else { - pawnBulk[WHITE] = (nrRanks == 7 ? 1 : 2); // board file considered full when total reaches 2 + pawnBulk[WHITE] = (maxDrop == 3 || nrRanks == 7 ? 1 : 2); // board file considered full when total reaches 2 } pawnBulk[BLACK] = 4*pawnBulk[WHITE]; maxBulk[BLACK] = 4*2; maxBulk[WHITE] = 2; // bits to test to see if file is full for specified side @@ -643,6 +664,23 @@ GameInit (char *name) kingPST[2*22] = kingPST[22*(nrRanks-3) + nrFiles - 1] = 0; for(f=0,p=pstType[v]; *p; p++,f++) if(*p == ' ') f = 15; else PST[BLACK+f] = (PST[WHITE+f] = pstData + 22*11*(*p - '0')) + 11*(*p > '2'); + if(v == KYOTO_NR) { // initialize Kyoto-Shogi PST from packed initialized data + static int bulk[4] = { 1, 3, 2, 3 }; + for(i=0; i<4; i++) { + PST[BLACK+i] = (PST[WHITE+i] = pstData + 11*22*(i+3)) + 11; // assign PST to pieces + PST[BLACK+i+16] = (PST[WHITE+i+16] = pstData + 11*22*(i+3) + 5*22) + 11; // hide two 5x5 PST in one 11x11 table + for(r=0; r<5; r++) for(f=0; f<3; f++) { + PST[BLACK+i][22*r+f] = PST[BLACK+i][22*r+4-f] = kyotoPST[i][3*r+f]; + PST[WHITE+i][22*r+f] = PST[WHITE+i][22*r+4-f] = kyotoPST[i][3*(4-r)+f]; + PST[BLACK+i+16][22*r+f] = PST[BLACK+i+16][22*r+4-f] = kyotoPST[i+4][3*r+f]; + PST[WHITE+i+16][22*r+f] = PST[WHITE+i+16][22*r+4-f] = kyotoPST[i+4][3*(4-r)+f]; + } + promoCode[i+16] = promoCode[i]; promoCode[i+16+WHITE] = promoCode[i+WHITE]; // let promoted types demote + PST[-1][handSlot[WHITE+i]] -= 125; PST[-1][handSlot[BLACK+i]] -= 125; + handBulk[handSlot[WHITE+i]] = handBulk[handSlot[BLACK+i]] = bulk[i]; // base bulk on promoted type + } + promoDrops = 1; promoGain[-1] = 125; + } InitCaptureCodes(variants[v].codes); pinCodes = (v == TORI_NR ? 0xFF2C : 0xFF1F); // rays along which pinning is possible @@ -1816,8 +1854,8 @@ printf("# command: %s\n", inBuf); } if(!strcmp(command, "protover")){ printf("feature ping=1 setboard=1 colors=0 usermove=1 memory=1 debug=1 reuse=0 sigint=0 sigterm=0 myname=\"CrazyWa " VERSION "\"\n"); - printf("feature variants=\"crazyhouse,shogi,minishogi,judkinshogi,torishogi,euroshogi,crazywa," - "5x5+5_shogi,6x6+6_shogi,7x7+6_shogi,11x17+16_chu\"\n"); + printf("feature variants=\"crazyhouse,shogi,minishogi,judkinshogi,torishogi,euroshogi,crazywa,kyotoshogi," + "5x5+4_shogi,5x5+5_shogi,6x6+6_shogi,7x7+6_shogi,11x17+16_chu\"\n"); printf("feature option=\"Resign -check 0\"\n"); // example of an engine-defined option printf("feature option=\"Contempt -spin 0 -200 200\"\n"); // and another one printf("feature done=1\n"); -- 1.7.0.4