X-Git-Url: http://winboard.nl/cgi-bin?p=capablanca.git;a=blobdiff_plain;f=lasker-2.2.3%2Fsrc%2Falgcheck.c;h=d0434450a3cbe6979021a95d9ed03fd38a6b627d;hp=32bdba100a1f380d4e7ce0cf199e4a1eaf208c7c;hb=fc8a38817986f2ad7a034db0d413762e509a7cac;hpb=76f1e81b3426b94e1d80c9daa309f78045e5335b diff --git a/lasker-2.2.3/src/algcheck.c b/lasker-2.2.3/src/algcheck.c old mode 100644 new mode 100755 index 32bdba1..d043445 --- a/lasker-2.2.3/src/algcheck.c +++ b/lasker-2.2.3/src/algcheck.c @@ -96,7 +96,7 @@ static int get_move_info(const char *str, int *piece, int *ff, int *fr, int *tf, 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'; @@ -104,12 +104,12 @@ static int get_move_info(const char *str, int *piece, int *ff, int *fr, int *tf, 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) + ltr = tmp[j] - '0'; // [HGM] allow 0-rank for Xiangqi, correct later + else + lfr = tmp[j] - '0'; break; case 'p': if (isupper(tmp[j])) @@ -118,8 +118,32 @@ static int get_move_info(const char *str, int *piece, int *ff, int *fr, int *tf, 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') @@ -190,7 +214,7 @@ int alg_is_move(const char *mstr) 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; @@ -199,14 +223,29 @@ static void add_promotion(struct game_state_t *gs, const char *mstr, struct move 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': + 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; @@ -214,12 +253,35 @@ static void add_promotion(struct game_state_t *gs, const char *mstr, struct move piece = BISHOP; break; case 'n': + if(gs->royalKnight) return; // [HGM] not in knightmate 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': + 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]); } @@ -233,6 +295,56 @@ int alg_parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt) d_printf( "CHESSD: Shouldn't try to algebraicly parse non-algabraic move string.\n"); return MOVE_ILLEGAL; } + + // [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, "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; + } + /* Resolve ambiguities in to-ness */ if (tf == ALG_UNKNOWN) { d_printf("Ambiguous %s(%d)\n", __FUNCTION__, __LINE__); @@ -250,7 +362,7 @@ int alg_parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt) } /* 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) @@ -286,25 +398,27 @@ int alg_parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt) 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; } @@ -322,7 +436,7 @@ int alg_parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt) 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)) @@ -381,20 +495,21 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) 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 + strcpy(mStr, "O-O"); + goto check; + } + if ((mt->fromFile == ALG_CASTLE) && (mt->toFile < mt->toRank)) { // [HGM] castle: K ends left of R + strcpy(mStr, "O-O-O"); + goto check; + } 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); } @@ -408,9 +523,68 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) case ROOK: strcpy(mStr, "R"); break; + case ALFIL2: + case AMAZON: + case CARDINAL: + strcpy(mStr, "A"); + break; + case CANNON: + case MARSHALL: + strcpy(mStr, "C"); + break; + case MAN: + strcpy(mStr, "M"); + break; + 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; @@ -425,8 +599,8 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) /* 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++) + 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))) { @@ -460,48 +634,78 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) } } } - 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) { + /* 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); + + 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 CARDINAL: + strcat(mStr, "A"); + break; + case MARSHALL: + strcat(mStr, "C"); + break; + case MAN: + strcat(mStr, "M"); + break; + case QUEEN: + strcat(mStr, "Q"); + break; + case FERZ2: + strcat(mStr, "F"); + break; + case WOODY: + strcat(mStr, "W"); + break; + 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: + strcat(mStr, "G"); + break; + default: + break; + } + } check:; fakeMove = *gs; execute_move(&fakeMove, mt, 0);