case 'r':
if ((tmp[j] < '0') || (tmp[j] > '9')) // [HGM] also match 0- and 9-rank
goto nomatch;
- if (ltr == ALG_UNKNOWN)\r
- ltr = tmp[j] - '0'; // [HGM] allow 0-rank for Xiangqi, correct later\r
- else\r
+ if (ltr == ALG_UNKNOWN)
+ ltr = tmp[j] - '0'; // [HGM] allow 0-rank for Xiangqi, correct later
+ else
lfr = tmp[j] - '0';
break;
case 'p':
lpiece = KNIGHT;
else if (c == 'p')
lpiece = PAWN;
+ else if (c == 'd')
+ lpiece = DRAGONKING;
else
goto nomatch;
break;
matchVal = i;
nomatch:;
}
+
if (matchVal != -1)
return MS_ALG;
else
if (s == NULL) {
return;
}
-
- if (piecetype(gs->board[mt->fromFile][mt->fromRank]) != PAWN) {
+ if(gs->promoType == 3) { // handle Shogi promotions
+ piece = gs->board[mt->fromFile][mt->fromRank];
+ if(colorval(piece) == WHITE && mt->fromRank < gs->ranks - gs->ranks/3
+ && mt->toRank < gs->ranks - gs->ranks/3 ) return;
+ if(colorval(piece) == BLACK && mt->fromRank >= gs->ranks/3
+ && mt->toRank >= gs->ranks/3 ) return;
+ switch(piecetype(piece)) {
+ case PAWN:
+ case LANCE:
+ case HONORABLEHORSE:
+ case SILVER:
+ if(s[1] != '+' && s[1] != '^' && s[1] != 'G' && s[1] != 'g') return;
+ piece = GOLD; break;
+ case BISHOP:
+ if(s[1] != '+' && s[1] != '^' && s[1] != 'H' && s[1] != 'h') return;
+ piece = DRAGONHORSE; break;
+ case ROOK:
+ if(s[1] != '+' && s[1] != '^' && s[1] != 'D' && s[1] != 'd') return;
+ piece = DRAGONKING; break;
+ default: return; // others do not promote, so ignore
+ }
+ mt->piecePromotionTo = piece | colorval(gs->board[mt->fromFile][mt->fromRank]);
+ return;
+ }
+
+ if(gs->drops != 2 || (gs->onMove == WHITE ? 0 : gs->ranks-1) != mt->fromRank) { // [HGM] always accept if backrank mover in Seirawan
+ if (piecetype(gs->board[mt->fromFile][mt->fromRank]) != PAWN &&
+ piecetype(gs->board[mt->fromFile][mt->fromRank]) != HOPLITE) {
return;
}
- if (mt->toRank != gs->ranks-1 && mt->toRank != 0) {
+ if (mt->toRank < gs->ranks - gs->promoZone && mt->toRank >= gs->promoZone) {
return;
}
+ }
switch (tolower(s[1])) {
case 'f':
case 'q':
piece = QUEEN;
break;
- case 'c':\r
- if(!gs->capablancaPieces) return; // [HGM] should make variant-dependent piece mask\r
- piece = MARSHALL;\r
- break;\r
- case 'a':\r
- if(!gs->capablancaPieces) return;\r
- piece = CARDINAL;\r
- break;\r
- case 'm':\r
- if(!gs->royalKnight) return; // [HGM] only in knightmate\r
- piece = MAN;\r
- break;\r
+ case 'c':
+ if(piecetype(gs->board[mt->fromFile][mt->fromRank]) == HOPLITE) piece = CAPTAIN; else
+ if(!gs->capablancaPieces) return; // [HGM] should make variant-dependent piece mask
+ piece = MARSHALL;
+ break;
+ case 'a':
+ if(!gs->capablancaPieces) return;
+ piece = CARDINAL;
+ break;
+ case 'm':
+ if(!gs->royalKnight) return; // [HGM] only in knightmate
+ piece = MAN;
+ break;
case 'r':
piece = ROOK;
break;
piece = BISHOP;
break;
case 'n':
- if(gs->royalKnight) return; // [HGM] not in knightmate\r
+ if(gs->royalKnight) return; // [HGM] not in knightmate
piece = KNIGHT;
break;
// Superchess promotons: filtered out later by promoType
case 'g':
+ if(piecetype(gs->board[mt->fromFile][mt->fromRank]) == HOPLITE) piece = GENERAL; else
piece = MASTODON;
break;
case 'o':
piece = SQUIRREL;
break;
case 'w':
+ if(piecetype(gs->board[mt->fromFile][mt->fromRank]) == HOPLITE) piece = WARLORD; else
piece = WOODY;
break;
+ case 'k':
+ if(piecetype(gs->board[mt->fromFile][mt->fromRank]) != HOPLITE) return;
+ piece = KING;
+ break;
+ case 'l':
+ if(piecetype(gs->board[mt->fromFile][mt->fromRank]) != HOPLITE) return;
+ piece = LIEUTENANT;
+ break;
case 'v':
piece = CENTAUR;
break;
- case 'e':\r
- piece = EMPRESS;
+ case 'e':
+ piece = gs->drops == 2 ? SELEPHANT : EMPRESS; // for Seirawan
break;
case 's':
piece = PRINCESS;
break;
+ case 'h':
+ if(gs->drops != 2) return;
+ piece = HAWK;
+ break;
default:
return;
}
-
i = colorval(gs->board[mt->fromFile][mt->fromRank]) == WHITE ? 0 : 1;
- if(piece >= WOODY && (gs->promoType != 2 || gs->holding[i][piece-1] == 0)) return;
+ if(gs->promoType == 2 && gs->holding[i][piece-1] == 0) return; // only if piece was captured
+ if(piece >= WOODY && piece < KING && (gs->promoType != 2 || gs->promoZone == 3)) return; // reserved for Superchess
mt->piecePromotionTo = piece | colorval(gs->board[mt->fromFile][mt->fromRank]);
}
d_printf( "CHESSD: Shouldn't try to algebraicly parse non-algabraic move string.\n");
return MOVE_ILLEGAL;
}
- \r
- // [HGM] check if move does not stray off board\r
- if(gs->ranks < 10) { \r
- if(tr == 0 || fr == 0) return MOVE_ILLEGAL; // used nonexistent 0-rank\r
- if(tr != ALG_UNKNOWN) tr--; if(fr != ALG_UNKNOWN) fr--; // shift to lowest rank = 1\r
- }\r
- if(tr >= gs->ranks || fr >= gs->ranks || tf >= gs->files || ff >= gs->files)\r
- return MOVE_ILLEGAL;\r
+ // [HGM] check if move does not stray off board
+ if(gs->ranks < 10) {
+ if(tr == 0 || fr == 0) return MOVE_ILLEGAL; // used nonexistent 0-rank
+ if(tr != ALG_UNKNOWN) tr--; if(fr != ALG_UNKNOWN) fr--; // shift to lowest rank = 1
+ }
+ if(tr >= gs->ranks || fr >= gs->ranks || tf >= gs->files || ff >= gs->files)
+ return MOVE_ILLEGAL;
// [HGM] resolve ambiguity in piece, type based on variant
switch(piece) {
case ELEPHANT:
if(strstr(gs->variant, "super")) piece = EMPRESS; else
+ if(strstr(gs->variant, "seirawan"))piece = SELEPHANT; else
if(strstr(gs->variant, "great")) piece = MODERNELEPHANT; else
if(strstr(gs->variant, "courier")) piece = ALFIL2;
break;
if(strstr(gs->variant, "great")) piece = MINISTER;
break;
case HORSE:
+ if(strstr(gs->variant, "shogi")) piece = DRAGONHORSE; else
+ if(strstr(gs->variant, "seirawan")) piece = HAWK; else
if(strstr(gs->variant, "great")) piece = PRIESTESS;
break;
case GOLD:
if(strstr(gs->variant, "great")) piece = MASTODON;
break;
}
-\r
+
/* Resolve ambiguities in to-ness */
if (tf == ALG_UNKNOWN) {
d_printf("Ambiguous %s(%d)\n", __FUNCTION__, __LINE__);
// note that the interpretation Bxc4 is matched last, and has set piece to BISHOP
continue;
}
-
if (legal_andcheck_move(gs, f, r, tf, tr)) {
if ((piecetype(gs->board[f][r]) == PAWN) && (f != tolower(mstr[0]) - 'a')) {
continue;
piece = piecetype(gs->board[mt->fromFile][mt->fromRank]);
}
- if ((mt->fromFile == ALG_CASTLE) && (mt->toFile > mt->toRank)) { // [HGM] castle: K ends right of R\r
- strcpy(mStr, "O-O");\r
- goto check;\r
- }\r
- if ((mt->fromFile == ALG_CASTLE) && (mt->toFile < mt->toRank)) { // [HGM] castle: K ends left of R\r
- strcpy(mStr, "O-O-O");\r
- goto check;\r
- }\r
+ if (mt->fromFile == ALG_CASTLE) {
+ int r = gs->onMove == WHITE ? 1 : gs->ranks;
+ if(mt->toFile > mt->toRank) { // [HGM] castle: K ends right of R
+ strcpy(mStr, "O-O");
+ }
+ if (mt->toFile < mt->toRank) { // [HGM] castle: K ends left of R
+ strcpy(mStr, "O-O-O");
+ }
+ if(gs->drops == 2) {
+ if(mt->piecePromotionTo < 0) snprintf(mStr, 20, "%c%de%d", mt->fromRank + 'a', r, r);
+ goto suffix; // [HGM] in Seirawan castling can have gating suffix
+ }
+ goto check;
+ }
strcpy(mStr, "");
switch (piece) {
case PAWN:
break;
case ALFIL2:
case AMAZON:
- case CARDINAL:\r
- strcpy(mStr, "A");\r
- break;\r
+ case CARDINAL:
+ strcpy(mStr, "A");
+ break;
+ case CAPTAIN:
case CANNON:
- case MARSHALL:\r
- strcpy(mStr, "C");\r
- break;\r
- case MAN:\r
- strcpy(mStr, "M");\r
- break;\r
+ case MARSHALL:
+ strcpy(mStr, "C");
+ break;
+ case MAN:
+ strcpy(mStr, "M");
+ break;
case FERZ:
case QUEEN:
strcpy(mStr, "Q");
break;
case EMPRESS:
case ELEPHANT:
+ case SELEPHANT:
strcpy(mStr, "E");
break;
case ALFIL:
case FERZ2:
strcpy(mStr, "F");
break;
+ case WARLORD:
case WOODY:
case WAZIR:
strcpy(mStr, "W");
strcpy(mStr, "V");
break;
case HORSE:
+ case DRAGONHORSE:
+ case HAWK:
+ case HOPLITE:
strcpy(mStr, "H");
break;
case HONORABLEHORSE:
strcpy(mStr, "N");
break;
case DRAGONKING:
- strcpy(mStr, "J");
- break;
- case DRAGONHORSE:
- strcpy(mStr, "I");
+ strcpy(mStr, "D");
break;
+ case LIEUTENANT:
case LANCE:
strcpy(mStr, "L");
break;
strcpy(mStr, "S");
break;
case MASTODON:
+ case GENERAL:
case GOLD:
strcpy(mStr, "G");
break;
/* Checks for ambiguity in short notation ( Ncb3, R8e8 or so) */
if (piece != PAWN) {
ambig = r_ambig = f_ambig = 0;
- for (r = 0; r < gs->ranks; r++)\r
- for (f = 0; f < gs->files; f++) {\r
+ for (r = 0; r < gs->ranks; r++)
+ for (f = 0; f < gs->files; f++) {
if ((gs->board[f][r] != NOPIECE) && iscolor(gs->board[f][r], gs->onMove)
&& (piecetype(gs->board[f][r]) == piece) &&
((f != mt->fromFile) || (r != mt->fromRank))) {
}
}
}
- if (ambig > 0) {\r
- /* Ambiguity in short notation, need to add file,rank or _both_ in\r
- notation */\r
- if (f_ambig == 0) {\r
- sprintf(tmp, "%c", mt->fromFile + 'a');\r
- strcat(mStr, tmp);\r
- } else if (r_ambig == 0) {\r
- sprintf(tmp, "%d", mt->fromRank + 1 - (gs->ranks > 9));\r
- strcat(mStr, tmp);\r
- } else {\r
- sprintf(tmp, "%c%d", mt->fromFile + 'a', mt->fromRank + 1 - (gs->ranks > 9));\r
- strcat(mStr, tmp);\r
- }\r
- }\r
- }\r
- if ((gs->board[mt->toFile][mt->toRank] != NOPIECE) ||\r
- ((piece == PAWN) && (mt->fromFile != mt->toFile))) {\r
- strcat(mStr, "x");\r
- }\r
- }\r
- sprintf(tmp, "%c%d", mt->toFile + 'a', mt->toRank + 1 - (gs->ranks > 9));\r
- strcat(mStr, tmp);\r
-
- if ((piece == PAWN || gs->promoType == 3) && (mt->piecePromotionTo != NOPIECE)) {\r
- strcat(mStr, "="); /* = before promoting piece */\r
- switch (piecetype(mt->piecePromotionTo)) {\r
- case KNIGHT:\r
- strcat(mStr, "N");\r
- break;\r
- case BISHOP:\r
- strcat(mStr, "B");\r
- break;\r
- case ROOK:\r
- strcat(mStr, "R");\r
- break;\r
- case CARDINAL:\r
- strcat(mStr, "A");\r
- break;\r
- case MARSHALL:\r
- strcat(mStr, "C");\r
- break;\r
- case MAN:\r
- strcat(mStr, "M");\r
- break;\r
- case QUEEN:\r
- strcat(mStr, "Q");\r
- break;\r
- case FERZ2:\r
- strcat(mStr, "F");\r
- break;\r
- case WOODY:\r
- strcat(mStr, "W");\r
- break;\r
- case EMPRESS:\r
- strcat(mStr, "E");\r
- break;\r
- case CENTAUR:\r
- strcat(mStr, "V");\r
- break;\r
- case PRINCESS:\r
- strcat(mStr, "S");\r
- break;\r
- case SQUIRREL:\r
- strcat(mStr, "O");\r
- break;\r
- case MASTODON:\r
- strcat(mStr, "G");\r
- break;\r
- case GOLD: // [HGM] Shogi promotions: avoid use of '+'\r
- strcat(mStr, "G");\r
- break;\r
- case DRAGONHORSE:\r
- strcat(mStr, "I");\r
- break;\r
- case DRAGONKING:\r
- strcat(mStr, "J");\r
- break;\r
- default:\r
- break;\r
- }\r
- }\r
+ if (ambig > 0) {
+ /* Ambiguity in short notation, need to add file,rank or _both_ in
+ notation */
+ if (f_ambig == 0) {
+ sprintf(tmp, "%c", mt->fromFile + 'a');
+ strcat(mStr, tmp);
+ } else if (r_ambig == 0) {
+ sprintf(tmp, "%d", mt->fromRank + 1 - (gs->ranks > 9));
+ strcat(mStr, tmp);
+ } else {
+ sprintf(tmp, "%c%d", mt->fromFile + 'a', mt->fromRank + 1 - (gs->ranks > 9));
+ strcat(mStr, tmp);
+ }
+ }
+ }
+ if ((gs->board[mt->toFile][mt->toRank] != NOPIECE) ||
+ ((piece == PAWN) && (mt->fromFile != mt->toFile))) {
+ strcat(mStr, "x");
+ }
+ }
+ sprintf(tmp, "%c%d", mt->toFile + 'a', mt->toRank + 1 - (gs->ranks > 9));
+ strcat(mStr, tmp);
+suffix:
+ if ((piece == PAWN || piece == HOPLITE || gs->promoType == 3 || gs->drops == 2) && (mt->piecePromotionTo != NOPIECE)) {
+ strcat(mStr, "="); /* = before promoting piece */
+ switch (piecetype(abs(mt->piecePromotionTo))) {
+ case KING:
+ strcat(mStr, "K");
+ break;
+ case KNIGHT:
+ strcat(mStr, "N");
+ break;
+ case BISHOP:
+ strcat(mStr, "B");
+ break;
+ case ROOK:
+ strcat(mStr, "R");
+ break;
+ case CARDINAL:
+ strcat(mStr, "A");
+ break;
+ case MARSHALL:
+ case CAPTAIN:
+ strcat(mStr, "C");
+ break;
+ case MAN:
+ strcat(mStr, "M");
+ break;
+ case QUEEN:
+ strcat(mStr, "Q");
+ break;
+ case FERZ2:
+ strcat(mStr, "F");
+ break;
+ case WARLORD:
+ case WOODY:
+ strcat(mStr, "W");
+ break;
+ case SELEPHANT:
+ case EMPRESS:
+ strcat(mStr, "E");
+ break;
+ case CENTAUR:
+ strcat(mStr, "V");
+ break;
+ case PRINCESS:
+ strcat(mStr, "S");
+ break;
+ case SQUIRREL:
+ strcat(mStr, "O");
+ break;
+ case MASTODON:
+ case GENERAL:
+ case GOLD: // [HGM] Shogi promotions: avoid use of '+'
+ strcat(mStr, "G");
+ break;
+ case HAWK:
+ case DRAGONHORSE:
+ strcat(mStr, "H");
+ break;
+ case DRAGONKING:
+ strcat(mStr, "D");
+ break;
+ case LIEUTENANT:
+ strcat(mStr, "L");
+ break;
+ default:
+ break;
+ }
+ }
check:;
fakeMove = *gs;
execute_move(&fakeMove, mt, 0);