for (j = len - 1; j >= 0; j--) {
switch (alg_list[i][j]) {
case 'f':
- if ((tmp[j] < 'a') || (tmp[j] > 'h'))
+ if ((tmp[j] < 'a') || (tmp[j] > 'l')) // [HGM] upto l-file
goto nomatch;
if (ltf == ALG_UNKNOWN)
ltf = tmp[j] - 'a';
lff = tmp[j] - 'a';
break;
case 'r':
- if ((tmp[j] < '1') || (tmp[j] > '8'))
+ if ((tmp[j] < '0') || (tmp[j] > '9')) // [HGM] also match 0- and 9-rank
goto nomatch;
- if (ltr == ALG_UNKNOWN)
- ltr = tmp[j] - '1';
- else
- lfr = tmp[j] - '1';
+ if (ltr == ALG_UNKNOWN)\r
+ ltr = tmp[j] - '0'; // [HGM] allow 0-rank for Xiangqi, correct later\r
+ else\r
+ lfr = tmp[j] - '0';
break;
case 'p':
if (isupper(tmp[j]))
c = tmp[j];
if (c == 'k')
lpiece = KING;
+ else if (c == 'e') // [HGM] note that som piece indicators are ambiguous,
+ lpiece = ELEPHANT; // and their true meaning depends on the variant,
+ else if (c == 'v') // which we do not know at this point.
+ lpiece = CENTAUR;
+ else if (c == 's')
+ lpiece = SILVER;
+ else if (c == 'g')
+ lpiece = GOLD;
+ else if (c == 'l')
+ lpiece = LANCE;
+ else if (c == 'f')
+ lpiece = FERZ;
+ else if (c == 'h')
+ lpiece = HORSE;
+ else if (c == 'w')
+ lpiece = WAZIR;
+ else if (c == 'o')
+ lpiece = SQUIRREL;
else if (c == 'q')
lpiece = QUEEN;
+ else if (c == 'c')
+ lpiece = MARSHALL;
+ else if (c == 'a')
+ lpiece = CARDINAL;
+ else if (c == 'm')
+ lpiece = MAN;
else if (c == 'r')
lpiece = ROOK;
else if (c == 'b')
static void add_promotion(struct game_state_t *gs, const char *mstr, struct move_t * mt)
{
char *s;
- int piece;
+ int piece, i;
s = strchr(mstr, '=');
if (s == NULL) {
return;
if (piecetype(gs->board[mt->fromFile][mt->fromRank]) != PAWN) {
return;
}
- if (mt->toRank != 7 && mt->toRank != 0) {
+ if (mt->toRank != gs->ranks-1 && mt->toRank != 0) {
return;
}
switch (tolower(s[1])) {
+ case 'f':
+ piece = FERZ2;
+ break;
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 'r':
piece = ROOK;
break;
piece = BISHOP;
break;
case 'n':
+ if(gs->royalKnight) return; // [HGM] not in knightmate\r
piece = KNIGHT;
break;
+ // Superchess promotons: filtered out later by promoType
+ case 'g':
+ piece = MASTODON;
+ break;
+ case 'o':
+ piece = SQUIRREL;
+ break;
+ case 'w':
+ piece = WOODY;
+ break;
+ case 'v':
+ piece = CENTAUR;
+ break;
+ case 'e':\r
+ piece = EMPRESS;
+ break;
+ case 's':
+ piece = PRINCESS;
+ 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;
+
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] resolve ambiguity in piece, type based on variant
+ switch(piece) {
+ case ELEPHANT:
+ if(strstr(gs->variant, "super")) piece = EMPRESS; else
+ if(strstr(gs->variant, "great")) piece = MODERNELEPHANT; else
+ if(strstr(gs->variant, "courier")) piece = ALFIL2;
+ break;
+ case CARDINAL:
+ if(strstr(gs->variant, "super")) piece = AMAZON; else
+ if(strstr(gs->variant, "xiangqi")) piece = MANDARIN;
+ break;
+ case MARSHALL:
+ if(strstr(gs->variant, "xiangqi")) piece = CANNON;
+ break;
+ case SILVER:
+ if(strstr(gs->variant, "super")) piece = PRINCESS;
+ if(strstr(gs->variant, "great")) piece = MAN2;
+ break;
+ case BISHOP:
+ if(strstr(gs->variant, "shatranj")) piece = ALFIL;
+ break;
+ case QUEEN:
+ if(strstr(gs->variant, "shatranj")) piece = FERZ;
+ break;
+ case WAZIR:
+ if(strstr(gs->variant, "super")) piece = WOODY;
+ break;
+ case KNIGHT:
+ if(strstr(gs->variant, "shogi")) piece = HONORABLEHORSE;
+ break;
+ case MAN:
+ if(strstr(gs->variant, "great")) piece = MINISTER;
+ break;
+ case HORSE:
+ 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__);
}
/* Need to find pawn on ff that can take to tf and fill in ranks */
for (InitPieceLoop(gs->board, &f, &r, gs->onMove);
- NextPieceLoop(gs->board, &f, &r, gs->onMove);) {
+ NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) {
if ((ff != ALG_UNKNOWN) && (ff != f))
continue;
if (piecetype(gs->board[f][r]) != piece)
ff = ALG_UNKNOWN;
fr = ALG_UNKNOWN;
for (InitPieceLoop(gs->board, &f, &r, gs->onMove);
- NextPieceLoop(gs->board, &f, &r, gs->onMove);) {
- if ((piecetype(gs->board[f][r]) != PAWN) && (piecetype(gs->board[f][r]) != BISHOP)) {
+ NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) {
+ if ((piecetype(gs->board[f][r]) != PAWN) && (piecetype(gs->board[f][r]) != piece)) {
+ // 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 != 1)) {
+ if ((piecetype(gs->board[f][r]) == PAWN) && (f != tolower(mstr[0]) - 'a')) {
continue;
}
/* if its a lowercase 'b' then prefer the pawn move if there is one */
if ((ff != ALG_UNKNOWN) && (fr != ALG_UNKNOWN) &&
- piecetype(gs->board[f][r]) == PAWN && mstr[0] == 'b') {
+ piecetype(gs->board[f][r]) == PAWN && mstr[0] >= 'a') {
ff = f;
fr = r;
continue;
}
if ((ff != ALG_UNKNOWN) && (fr != ALG_UNKNOWN) &&
- piecetype(gs->board[ff][fr]) == PAWN && mstr[0] == 'b') {
+ piecetype(gs->board[ff][fr]) == PAWN && mstr[0] >= 'a') {
continue;
}
if ((ff == ALG_UNKNOWN) || (fr == ALG_UNKNOWN)) {
/* Need to find a piece that can go to tf, tr */
for (InitPieceLoop(gs->board, &f, &r, gs->onMove);
- NextPieceLoop(gs->board, &f, &r, gs->onMove);) {
+ NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) {
if ((ff != ALG_UNKNOWN) && (ff != f))
continue;
if ((fr != ALG_UNKNOWN) && (fr != r))
piece = piecetype(gs->board[mt->fromFile][mt->fromRank]);
}
- if ((piece == KING) && ((mt->fromFile == 4) && (mt->toFile == 6))) {
- strcpy(mStr, "O-O");
- goto check;
- }
- if ((piece == KING) && ((mt->fromFile == 4) && (mt->toFile == 2))) {
- strcpy(mStr, "O-O-O");
- goto check;
- }
+ 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
strcpy(mStr, "");
switch (piece) {
case PAWN:
if (mt->fromFile == ALG_DROP) {
strcpy(mStr,"P");
- } else if (mt->fromFile != mt->toFile) {
+ } else if (mt->fromFile != mt->toFile
+ || gs->board[mt->toFile][mt->toRank] != NOPIECE) { // [HGM] XQ: forward captures as "axa6"
sprintf(tmp, "%c", mt->fromFile + 'a');
strcpy(mStr, tmp);
}
case ROOK:
strcpy(mStr, "R");
break;
+ case ALFIL2:
+ case AMAZON:
+ case CARDINAL:\r
+ strcpy(mStr, "A");\r
+ break;\r
+ case CANNON:
+ case MARSHALL:\r
+ strcpy(mStr, "C");\r
+ break;\r
+ case MAN:\r
+ strcpy(mStr, "M");\r
+ break;\r
+ case FERZ:
case QUEEN:
strcpy(mStr, "Q");
break;
+ case EMPRESS:
+ case ELEPHANT:
+ strcpy(mStr, "E");
+ break;
+ case ALFIL:
+ strcpy(mStr, "B");
+ break;
+ case FERZ2:
+ strcpy(mStr, "F");
+ break;
+ case WOODY:
+ case WAZIR:
+ strcpy(mStr, "W");
+ break;
+ case SQUIRREL:
+ strcpy(mStr, "O");
+ break;
+ case CENTAUR:
+ strcpy(mStr, "V");
+ break;
+ case HORSE:
+ strcpy(mStr, "H");
+ break;
+ case HONORABLEHORSE:
+ strcpy(mStr, "N");
+ break;
+ case DRAGONKING:
+ strcpy(mStr, "J");
+ break;
+ case DRAGONHORSE:
+ strcpy(mStr, "I");
+ break;
+ case LANCE:
+ strcpy(mStr, "L");
+ break;
+ case PRINCESS:
+ case SILVER:
+ strcpy(mStr, "S");
+ break;
+ case MASTODON:
+ case GOLD:
+ strcpy(mStr, "G");
+ break;
+ case MANDARIN:
+ strcpy(mStr, "A");
+ break;
case KING:
strcpy(mStr, "K");
break;
/* Checks for ambiguity in short notation ( Ncb3, R8e8 or so) */
if (piece != PAWN) {
ambig = r_ambig = f_ambig = 0;
- for (r = 0; r < 8; r++)
- for (f = 0; f < 8; f++) {
+ for (r = 0; r < gs->ranks; r++)\r
+ for (f = 0; f < gs->files; f++) {\r
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) {
- /* 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);
- strcat(mStr, tmp);
- } else {
- sprintf(tmp, "%c%d", mt->fromFile + 'a', mt->fromRank + 1);
- 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);
- strcat(mStr, tmp);
-
- if ((piece == PAWN) && (mt->piecePromotionTo != NOPIECE)) {
- strcat(mStr, "="); /* = before promoting piece */
- switch (piecetype(mt->piecePromotionTo)) {
- case KNIGHT:
- strcat(mStr, "N");
- break;
- case BISHOP:
- strcat(mStr, "B");
- break;
- case ROOK:
- strcat(mStr, "R");
- break;
- case QUEEN:
- strcat(mStr, "Q");
- break;
- default:
- break;
- }
- }
+ 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
+\r
+ if ((piece == PAWN) && (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
+ default:\r
+ break;\r
+ }\r
+ }\r
check:;
fakeMove = *gs;
execute_move(&fakeMove, mt, 0);