X-Git-Url: http://winboard.nl/cgi-bin?p=capablanca.git;a=blobdiff_plain;f=lasker-2.2.3%2Fsrc%2Falgcheck.c;h=aa7d5af20234175f5e72457413e08fda8c3ca4e7;hp=32bdba100a1f380d4e7ce0cf199e4a1eaf208c7c;hb=ec7b6bb32ba9632cda17b308808ce9ba1e27c090;hpb=76f1e81b3426b94e1d80c9daa309f78045e5335b diff --git a/lasker-2.2.3/src/algcheck.c b/lasker-2.2.3/src/algcheck.c index 32bdba1..aa7d5af 100644 --- 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'; + ltr = tmp[j] - '0'; // [HGM] allow 0-rank for Xiangqi, correct later else - lfr = tmp[j] - '1'; + 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') @@ -128,6 +152,8 @@ static int get_move_info(const char *str, int *piece, int *ff, int *fr, int *tf, lpiece = KNIGHT; else if (c == 'p') lpiece = PAWN; + else if (c == 'd') + lpiece = DRAGONKING; else goto nomatch; break; @@ -173,6 +199,7 @@ static int get_move_info(const char *str, int *piece, int *ff, int *fr, int *tf, matchVal = i; nomatch:; } + if (matchVal != -1) return MS_ALG; else @@ -190,23 +217,62 @@ 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; } - + 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 (piecetype(gs->board[mt->fromFile][mt->fromRank]) != PAWN) { return; } - if (mt->toRank != 7 && mt->toRank != 0) { + if (mt->toRank < gs->ranks - gs->promoZone && mt->toRank >= gs->promoZone) { 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,11 +280,38 @@ 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 = 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(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]); } @@ -233,6 +326,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; + if(strstr(gs->variant, "shogi")) piece = DRAGONHORSE; + 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 +393,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 +429,26 @@ 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 +466,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,11 +525,11 @@ 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))) { + if ((mt->fromFile == ALG_CASTLE) && (mt->toFile > mt->toRank)) { // [HGM] castle: K ends right of R strcpy(mStr, "O-O"); goto check; } - if ((piece == KING) && ((mt->fromFile == 4) && (mt->toFile == 2))) { + if ((mt->fromFile == ALG_CASTLE) && (mt->toFile < mt->toRank)) { // [HGM] castle: K ends left of R strcpy(mStr, "O-O-O"); goto check; } @@ -394,7 +538,8 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) 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 +553,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, "D"); + break; + case DRAGONHORSE: + strcpy(mStr, "H"); + 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 +629,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))) { @@ -467,10 +671,10 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) sprintf(tmp, "%c", mt->fromFile + 'a'); strcat(mStr, tmp); } else if (r_ambig == 0) { - sprintf(tmp, "%d", mt->fromRank + 1); + sprintf(tmp, "%d", mt->fromRank + 1 - (gs->ranks > 9)); strcat(mStr, tmp); } else { - sprintf(tmp, "%c%d", mt->fromFile + 'a', mt->fromRank + 1); + sprintf(tmp, "%c%d", mt->fromFile + 'a', mt->fromRank + 1 - (gs->ranks > 9)); strcat(mStr, tmp); } } @@ -480,10 +684,10 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) strcat(mStr, "x"); } } - sprintf(tmp, "%c%d", mt->toFile + 'a', mt->toRank + 1); + sprintf(tmp, "%c%d", mt->toFile + 'a', mt->toRank + 1 - (gs->ranks > 9)); strcat(mStr, tmp); - if ((piece == PAWN) && (mt->piecePromotionTo != NOPIECE)) { + if ((piece == PAWN || gs->promoType == 3) && (mt->piecePromotionTo != NOPIECE)) { strcat(mStr, "="); /* = before promoting piece */ switch (piecetype(mt->piecePromotionTo)) { case KNIGHT: @@ -495,9 +699,50 @@ char *alg_unparse(struct game_state_t * gs, struct move_t * mt) 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 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: + strcat(mStr, "G"); + break; + 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; default: break; }