diff options
author | Markus Uhlin <markus@nifty-networks.net> | 2024-04-13 13:14:37 +0200 |
---|---|---|
committer | Markus Uhlin <markus@nifty-networks.net> | 2024-04-13 13:14:37 +0200 |
commit | 754e9f069f9a937fe98bb392f425381e5ce04c0b (patch) | |
tree | 7efeaa1c2b39d4a7b99a41790a0b1c1f2e45bd18 /FICS/algcheck.c | |
parent | fd24f8d55b89ab4750c6618d02d58b78d455f59f (diff) |
Checked out files by tag 1.0
Diffstat (limited to 'FICS/algcheck.c')
-rw-r--r-- | FICS/algcheck.c | 854 |
1 files changed, 385 insertions, 469 deletions
diff --git a/FICS/algcheck.c b/FICS/algcheck.c index 67609b1..10fad0c 100644 --- a/FICS/algcheck.c +++ b/FICS/algcheck.c @@ -19,25 +19,17 @@ /* Revision history: name email yy/mm/dd Change - Richard Nash 93/10/22 Created - Markus Uhlin 24/01/04 Reformatted functions - Markus Uhlin 24/01/06 Switched to usage of strlcpy, - strlcat and snprintf. Also added - truncation checks. + Richard Nash 93/10/22 Created */ #include "stdinclude.h" -#include "common.h" +#include "common.h" #include "algcheck.h" -#include "board.h" #include "movecheck.h" +#include "board.h" #include "utils.h" -#if __linux__ -#include <bsd/string.h> -#endif - /* Well, lets see if I can list the possibilities * Piece moves * Ne4 @@ -66,484 +58,408 @@ * x - x * @ - drop character (bughouse) */ -PRIVATE char *alg_list[] = { - "fxfr", "pxfr", /* These two get confused in case of bishop */ - "ffr", "pfr", /* These two get confused in case of bishop */ - "pffr", - "pfxfr", - "prfr", - "prxfr", - "fr", - "ff", - "fxf", - "p@fr", - "#fr", - "#pfr", - NULL +char *alg_list[] = { + "fxfr", "pxfr", /* These two get confused in case of bishop */ + "ffr", "pfr", /* These two get confused in case of bishop */ + "pffr", + "pfxfr", + "prfr", + "prxfr", + "fr", + "ff", + "fxf", + "p@fr", + "#fr", + "#pfr", + NULL }; -PRIVATE int -get_move_info(char *str, int *piece, int *ff, int *fr, int *tf, int *tr, - int *bishconfusion) -{ - char *s; - char c; - char tmp[1024] = { '\0' }; - int i, j, len; - int lpiece, lff, lfr, ltf, ltr; - int matchVal = -1; - - *bishconfusion = 0; - strlcpy(tmp, str, sizeof tmp); - - if ((s = strchr(tmp, '+')) != NULL) { // Cut off any check marks - *s = '\0'; - } - if ((s = strchr(tmp, '=')) != NULL) { // Cut off any promotion marks - *s = '\0'; - } - - *piece = *ff = *fr = *tf = *tr = ALG_UNKNOWN; - len = strlen(tmp); - - for (i = 0; alg_list[i]; i++) { - lpiece = lff = lfr = ltf = ltr = ALG_UNKNOWN; - - if (strlen(alg_list[i]) != len) - continue; - - for (j = len - 1; j >= 0; j--) { - switch (alg_list[i][j]) { - case 'f': - if (tmp[j] < 'a' || tmp[j] > 'h') - goto nomatch; - - if (ltf == ALG_UNKNOWN) - ltf = (tmp[j] - 'a'); - else - lff = (tmp[j] - 'a'); - break; - case 'r': - if (tmp[j] < '1' || tmp[j] > '8') - goto nomatch; - - if (ltr == ALG_UNKNOWN) - ltr = (tmp[j] - '1'); - else - lfr = (tmp[j] - '1'); - break; - case 'p': - if (isupper(tmp[j])) - c = tolower(tmp[j]); - else - c = tmp[j]; - - if (c == 'k') - lpiece = KING; - else if (c == 'q') - lpiece = QUEEN; - else if (c == 'r') - lpiece = ROOK; - else if (c == 'b') - lpiece = BISHOP; - else if (c == 'n') - lpiece = KNIGHT; - else if (c == 'p') - lpiece = PAWN; - else - goto nomatch; - break; - case 'x': - if (tmp[j] != 'x' && tmp[j] != 'X') - goto nomatch; - break; - case '@': - if (tmp[j] != '@' && tmp[j] != '*') - goto nomatch; - lff = lfr = ALG_DROP; - break; - case '#': - if (tmp[j] != '#') - goto nomatch; - lff = lfr = ALG_DROP; - break; - default: - fprintf(stderr, "Unknown character in " - "algebraic parsing\n"); - break; - } - } - - if (lpiece == ALG_UNKNOWN) - lpiece = PAWN; - - if (lpiece == PAWN && lfr == ALG_UNKNOWN) { // ffr or ff - if (lff != ALG_UNKNOWN) { - if (lff == ltf) - goto nomatch; - if ((lff - ltf) != 1 && (ltf - lff) != 1) - goto nomatch; - } - } - - *piece = lpiece; // We have a match - - *tf = ltf; - *tr = ltr; - *ff = lff; - *fr = lfr; - - if (matchVal != -1) { - /* - * We have two matches, it must be that Bxc4 - * vs. bxc4 problem. Or it could be the Bc4 vs - * bc4 problem. - */ - *bishconfusion = 1; - } +#define ALG_UNKNOWN -1 +/* #define ALG_DROP -2 IanO: this is in board.h, used in movecheck.c */ - matchVal = i; - - nomatch:; - } - - if (matchVal != -1) - return MS_ALG; +PRIVATE int get_move_info(char *str, int *piece, int *ff, int *fr, int *tf, int *tr, int *bishconfusion) +{ + char tmp[1024]; + char *s; + int i, j, len; + char c; + int matchVal = -1; + int lpiece, lff, lfr, ltf, ltr; + + *bishconfusion = 0; + strcpy(tmp, str); + if ((s = index(tmp, '+'))) { /* Cut off any check marks */ + *s = '\0'; + } + if ((s = index(tmp, '='))) { /* Cut off any promotion marks */ + *s = '\0'; + } + *piece = *ff = *fr = *tf = *tr = ALG_UNKNOWN; + len = strlen(tmp); + for (i = 0; alg_list[i]; i++) { + lpiece = lff = lfr = ltf = ltr = ALG_UNKNOWN; + if (strlen(alg_list[i]) != len) + continue; + for (j = len - 1; j >= 0; j--) { + switch (alg_list[i][j]) { + case 'f': + if ((tmp[j] < 'a') || (tmp[j] > 'h')) + goto nomatch; + if (ltf == ALG_UNKNOWN) + ltf = tmp[j] - 'a'; + else + lff = tmp[j] - 'a'; + break; + case 'r': + if ((tmp[j] < '1') || (tmp[j] > '8')) + goto nomatch; + if (ltr == ALG_UNKNOWN) + ltr = tmp[j] - '1'; + else + lfr = tmp[j] - '1'; + break; + case 'p': + if (isupper(tmp[j])) + c = tolower(tmp[j]); else - return MS_NOTMOVE; + c = tmp[j]; + if (c == 'k') + lpiece = KING; + else if (c == 'q') + lpiece = QUEEN; + else if (c == 'r') + lpiece = ROOK; + else if (c == 'b') + lpiece = BISHOP; + else if (c == 'n') + lpiece = KNIGHT; + else if (c == 'p') + lpiece = PAWN; + else + goto nomatch; + break; + case 'x': + if ((tmp[j] != 'x') && (tmp[j] != 'X')) + goto nomatch; + break; + case '@': + if (tmp[j] != '@' && tmp[j] != '*') + goto nomatch; + lff = lfr = ALG_DROP; + break; + case '#': + if (tmp[j] != '#') + goto nomatch; + lff = lfr = ALG_DROP; + break; + default: + fprintf(stderr, "Unknown character in algebraic parsing\n"); + break; + } + } + if (lpiece == ALG_UNKNOWN) + lpiece = PAWN; + if (lpiece == PAWN && (lfr == ALG_UNKNOWN)) { /* ffr or ff */ + if (lff != ALG_UNKNOWN) { + if (lff == ltf) + goto nomatch; + if ((lff - ltf != 1) && (ltf - lff != 1)) + goto nomatch; + } + } + *piece = lpiece; /* We have a match */ + *tf = ltf; + *tr = ltr; + *ff = lff; + *fr = lfr; + if (matchVal != -1) { + /* We have two matches, it must be that Bxc4 vs. bxc4 problem */ + /* Or it could be the Bc4 vs bc4 problem */ + *bishconfusion = 1; + } + matchVal = i; +nomatch:; + } + if (matchVal != -1) + return MS_ALG; + else + return MS_NOTMOVE; } -PUBLIC int -alg_is_move(char *mstr) +PUBLIC int alg_is_move(char *mstr) { - int piece, ff, fr, tf, tr, bc; + int piece, ff, fr, tf, tr, bc; - return get_move_info(mstr, &piece, &ff, &fr, &tf, &tr, &bc); + return get_move_info(mstr, &piece, &ff, &fr, &tf, &tr, &bc); } -/* - * We already know it is algebraic. Get the move squares. - */ -PUBLIC int -alg_parse_move(char *mstr, game_state_t *gs, move_t *mt) +/* We already know it is algebraic, get the move squares */ +PUBLIC int alg_parse_move(char *mstr, game_state_t * gs, move_t * mt) { - int f, r, tmpr, posf, posr, posr2; - int piece, ff, fr, tf, tr, bc; - - if (get_move_info(mstr, &piece, &ff, &fr, &tf, &tr, &bc) != MS_ALG) { - fprintf(stderr, "FICS: Shouldn't try to algebraically parse " - "non-algebraic move string.\n"); - return MOVE_ILLEGAL; - } - - if (tf == ALG_UNKNOWN) - return MOVE_AMBIGUOUS; /* Must always know to file */ - - if (tr == ALG_UNKNOWN) { - posr = posr2 = ALG_UNKNOWN; - - if (piece != PAWN) - return MOVE_AMBIGUOUS; - if (ff == ALG_UNKNOWN) - return MOVE_AMBIGUOUS; - - /* - * 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);) { - if (ff != ALG_UNKNOWN && ff != f) - continue; - if (piecetype(gs->board[f][r]) != piece) - continue; - - if (gs->onMove == WHITE) { - tmpr = r + 1; - } else { - tmpr = r - 1; - } - - if (gs->board[tf][tmpr] == NOPIECE) { - const int is_black = (gs->onMove == WHITE ? - 0 : 1); - - if (gs->ep_possible[is_black][ff] != (tf - ff)) - continue; - } else { - if (iscolor(gs->board[tf][tmpr], gs->onMove)) - continue; - } - - if (legal_andcheck_move(gs, f, r, tf, tmpr)) { - if (posr != ALG_UNKNOWN && posr2 != ALG_UNKNOWN) - return MOVE_AMBIGUOUS; - - posr = tmpr; - posr2 = r; - } - } - - tr = posr; - fr = posr2; - } else if (bc) { /* Could be bxc4 or Bxc4, tr is known. */ - 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) - continue; - if (legal_andcheck_move(gs, f, r, tf, tr)) { - if (piecetype(gs->board[f][r]) == PAWN && - f != 1) - continue; - if (ff != ALG_UNKNOWN && fr != ALG_UNKNOWN) - return (MOVE_AMBIGUOUS); - - ff = f; - fr = r; - } - } - } else { /* The from position is unknown */ - posf = ALG_UNKNOWN; - posr = ALG_UNKNOWN; - - 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);) { - if (ff != ALG_UNKNOWN && ff != f) - continue; - if (fr != ALG_UNKNOWN && fr != r) - continue; - if (piecetype(gs->board[f][r]) != piece) - continue; - - if (legal_andcheck_move(gs, f, r, tf, tr)) { - if (posf != ALG_UNKNOWN && - posr != ALG_UNKNOWN) - return MOVE_AMBIGUOUS; - - posf = f; - posr = r; - } - } - } else if (ff == ALG_DROP) { - if (legal_andcheck_move(gs, ALG_DROP, piece, tf, tr)) { - posf = ALG_DROP; - posr = piece; - } - } - - ff = posf; - fr = posr; + int f, r, tmpr, posf, posr, posr2; + int piece, ff, fr, tf, tr, bc; + + if (get_move_info(mstr, &piece, &ff, &fr, &tf, &tr, &bc) != MS_ALG) { + fprintf(stderr, "FICS: Shouldn't try to algebraicly parse non-algabraic move string.\n"); + return MOVE_ILLEGAL; + } + /* Resolve ambiguities in to-ness */ + if (tf == ALG_UNKNOWN) + return MOVE_AMBIGUOUS; /* Must always know to file */ + if (tr == ALG_UNKNOWN) { + posr = posr2 = ALG_UNKNOWN; + if (piece != PAWN) + return MOVE_AMBIGUOUS; + if (ff == ALG_UNKNOWN) + return MOVE_AMBIGUOUS; + /* 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);) { + if ((ff != ALG_UNKNOWN) && (ff != f)) + continue; + if (piecetype(gs->board[f][r]) != piece) + continue; + if (gs->onMove == WHITE) { + tmpr = r + 1; + } else { + tmpr = r - 1; + } +/* if ((gs->board[tf][tmpr] == NOPIECE) || + (iscolor(gs->board[tf][tmpr], gs->onMove))) continue;*/ +/* patch from Soso, added by Sparky 3/16/95 */ + if (gs->board[tf][tmpr] == NOPIECE) { + if ((gs->ep_possible[((gs->onMove == WHITE) ? 0 : 1)][ff]) != (tf - ff)) + continue; + } else { + if (iscolor(gs->board[tf][tmpr], gs->onMove)) + continue; + } + + if (legal_andcheck_move(gs, f, r, tf, tmpr)) { + if ((posr != ALG_UNKNOWN) && (posr2 != ALG_UNKNOWN)) + return MOVE_AMBIGUOUS; + posr = tmpr; + posr2 = r; + } + } + tr = posr; + fr = posr2; + } else if (bc) { /* Could be bxc4 or Bxc4, tr is known */ + 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)) + continue; + if (legal_andcheck_move(gs, f, r, tf, tr)) { + if ((piecetype(gs->board[f][r]) == PAWN) && (f != 1)) + continue; + if ((ff != ALG_UNKNOWN) && (fr != ALG_UNKNOWN)) + return (MOVE_AMBIGUOUS); + ff = f; + fr = r; + } + } + } else { /* The from position is unknown */ + posf = ALG_UNKNOWN; + posr = ALG_UNKNOWN; + 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);) { + if ((ff != ALG_UNKNOWN) && (ff != f)) + continue; + if ((fr != ALG_UNKNOWN) && (fr != r)) + continue; + if (piecetype(gs->board[f][r]) != piece) + continue; + if (legal_andcheck_move(gs, f, r, tf, tr)) { + if ((posf != ALG_UNKNOWN) && (posr != ALG_UNKNOWN)) + return MOVE_AMBIGUOUS; + posf = f; + posr = r; } - - if (tf == ALG_UNKNOWN || tr == ALG_UNKNOWN || ff == ALG_UNKNOWN || - fr == ALG_UNKNOWN) - return MOVE_ILLEGAL; - - mt->fromFile = ff; - mt->fromRank = fr; - mt->toFile = tf; - mt->toRank = tr; - - return MOVE_OK; + } + } else if (ff == ALG_DROP) { + if (legal_andcheck_move(gs, ALG_DROP, piece, tf, tr)) { + posf = ALG_DROP; + posr = piece; + } + } + ff = posf; + fr = posr; + } + if ((tf == ALG_UNKNOWN) || (tr == ALG_UNKNOWN) || + (ff == ALG_UNKNOWN) || (fr == ALG_UNKNOWN)) + return MOVE_ILLEGAL; + mt->fromFile = ff; + mt->fromRank = fr; + mt->toFile = tf; + mt->toRank = tr; + return MOVE_OK; } -PRIVATE void -not_pawn(game_state_t *gs, move_t *mt, game_state_t *fakeMove, const int piece, - char *tmp, char *mStr, size_t tmp_size, size_t mStr_size) +/* A assumes the move has yet to be made on the board */ +/* this is the old stupid function, we are testing one from soso... +PUBLIC char *alg_unparse( game_state_t *gs, move_t *mt ) { - int ambig, r_ambig, f_ambig; - - ambig = r_ambig = f_ambig = 0; - - for (int r = 0; r < 8; r++) { - for (int f = 0; f < 8; 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 (legal_move(gs, f, r, mt->toFile, - mt->toRank)) { - fakeMove = gs; - fakeMove->board[f][r] = NOPIECE; - fakeMove->onMove = - CToggle(fakeMove->onMove); - gs->onMove = CToggle(gs->onMove); - - /* - * New bracketing below to try - * to fix 'ambiguous move' - * bug. - */ - - if (in_check(gs) || !in_check(fakeMove)) - ambig++; - - if (f == mt->fromFile) { - f_ambig++; - ambig++; - } - if (r == mt->fromRank) { - r_ambig++; - ambig++; - } - - gs->onMove = CToggle(gs->onMove); - } - } - } /* for */ - } /* for */ - - if (ambig > 0) { - /* - * Ambiguity in short notation. Need to add file, rank - * or _both_ in notation. - */ - - if (f_ambig == 0) { - snprintf(tmp, tmp_size, "%c", (mt->fromFile + 'a')); - strlcat(mStr, tmp, mStr_size); - } else if (r_ambig == 0) { - snprintf(tmp, tmp_size, "%d", (mt->fromRank + 1)); - strlcat(mStr, tmp, mStr_size); - } else { - snprintf(tmp, tmp_size, "%c%d", - (mt->fromFile + 'a'), - (mt->fromRank + 1)); - strlcat(mStr, tmp, mStr_size); - } - } + static char mStr[20]; + + if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == KING) && + ((mt->fromFile == 4) && (mt->toFile == 6)) ) + return "o-o"; + if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == KING) && + ((mt->fromFile == 4) && (mt->toFile == 2)) ) + return "o-o-o"; + + sprintf( mStr, "%c%d%c%d", mt->fromFile+'a', mt->fromRank+1, + mt->toFile+'a', mt->toRank+1 ); + return mStr; } +*/ -/* - * Soso: rewrote alg_unparse function. Algebraic deparser - sets the - * 'mStr' variable with move description in short notation. Used in - * last move report and in 'moves' command. - */ -PUBLIC char * -alg_unparse(game_state_t *gs, move_t *mt) -{ - char tmp[20] = { '\0' }; - game_state_t fakeMove; - int piece; - size_t ret = 0; - static char mStr[20] = { '\0' }; - - if (mt->fromFile == ALG_DROP) { - piece = mt->fromRank; - } else { - piece = piecetype(gs->board[mt->fromFile][mt->fromRank]); - } - - if (piece == KING && (mt->fromFile == 4 && mt->toFile == 6)) { - strlcpy(mStr, "O-O", sizeof mStr); - goto check; - } - - if (piece == KING && (mt->fromFile == 4 && mt->toFile == 2)) { - strlcpy(mStr, "O-O-O", sizeof mStr); - goto check; - } - - mStr[0] = '\0'; - - switch (piece) { - case PAWN: - if (mt->fromFile == ALG_DROP) { - strlcpy(mStr, "P", sizeof mStr); - } else if (mt->fromFile != mt->toFile) { - snprintf(tmp, sizeof tmp, "%c", (mt->fromFile + 'a')); - strlcpy(mStr, tmp, sizeof mStr); - } - break; - case KNIGHT: - strlcpy(mStr, "N", sizeof mStr); - break; - case BISHOP: - strlcpy(mStr, "B", sizeof mStr); - break; - case ROOK: - strlcpy(mStr, "R", sizeof mStr); - break; - case QUEEN: - strlcpy(mStr, "Q", sizeof mStr); - break; - case KING: - strlcpy(mStr, "K", sizeof mStr); - break; - default: - strlcpy(mStr, "", sizeof mStr); - break; - } /* switch */ - - if (mt->fromFile == ALG_DROP) { - strlcat(mStr, DROP_STR, sizeof mStr); - } else { - /* - * Checks for ambiguity in short notation (Ncb3, R8e8 - * or so.) - */ - - if (piece != PAWN) { - not_pawn(gs, mt, &fakeMove, piece, &tmp[0], &mStr[0], - sizeof tmp, sizeof mStr); - } /* not pawn */ - - if (gs->board[mt->toFile][mt->toRank] != NOPIECE || - (piece == PAWN && mt->fromFile != mt->toFile)) - strlcat(mStr, "x", sizeof mStr); - } - - snprintf(tmp, sizeof tmp, "%c%d", (mt->toFile + 'a'), (mt->toRank + 1)); - ret = strlcat(mStr, tmp, sizeof mStr); - - if (ret >= sizeof mStr) { - fprintf(stderr, "FICS: %s (line %d): warning: " - "strlcat() truncated\n", __func__, __LINE__); - } - - if (piece == PAWN && mt->piecePromotionTo != NOPIECE) { - strlcat(mStr, "=", sizeof mStr); /* = before promoting piece */ - - switch (piecetype(mt->piecePromotionTo)) { - case KNIGHT: - strlcat(mStr, "N", sizeof mStr); - break; - case BISHOP: - strlcat(mStr, "B", sizeof mStr); - break; - case ROOK: - strlcat(mStr, "R", sizeof mStr); - break; - case QUEEN: - strlcat(mStr, "Q", sizeof mStr); - break; - default: - break; - } - } - check:; +/* A assumes the move has yet to be made on the board */ - fakeMove = *gs; - execute_move(&fakeMove, mt, 0); - fakeMove.onMove = CToggle(fakeMove.onMove); - if (in_check(&fakeMove)) { - ret = strlcat(mStr, "+", sizeof mStr); +/* Soso: rewrote alg_unparse function. + * Algebraic deparser - sets the mStr variable with move description + * in short notation. Used in last move report and in 'moves' command. + */ - if (ret >= sizeof mStr) { - fprintf(stderr, "FICS: %s (line %d): warning: " - "strlcat() truncated\n", __func__, __LINE__); - } +PUBLIC char *alg_unparse(game_state_t * gs, move_t * mt) +{ + static char mStr[20]; + char tmp[20]; + int piece, f, r; + int ambig, r_ambig, f_ambig; + game_state_t fakeMove; + + if (mt->fromFile == ALG_DROP) { + piece = mt->fromRank; + } else { + 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; + } + strcpy(mStr, ""); + switch (piece) { + case PAWN: + if (mt->fromFile == ALG_DROP) { + strcpy(mStr,"P"); + } else if (mt->fromFile != mt->toFile) { + sprintf(tmp, "%c", mt->fromFile + 'a'); + strcpy(mStr, tmp); + } + break; + case KNIGHT: + strcpy(mStr, "N"); + break; + case BISHOP: + strcpy(mStr, "B"); + break; + case ROOK: + strcpy(mStr, "R"); + break; + case QUEEN: + strcpy(mStr, "Q"); + break; + case KING: + strcpy(mStr, "K"); + break; + default: + strcpy(mStr, ""); + break; + } + + if (mt->fromFile == ALG_DROP) { + strcat(mStr, DROP_STR); + } else { + /* 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++) { + 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 (legal_move(gs, f, r, mt->toFile, mt->toRank)) { + fakeMove = *gs; + fakeMove.board[f][r] = NOPIECE; + fakeMove.onMove = CToggle(fakeMove.onMove); + gs->onMove = CToggle(gs->onMove); + + /* New bracketing below to try to fix 'ambiguous move' bug. */ + if ((in_check(gs)) || !in_check(&fakeMove)) { + ambig++; + } + if (f == mt->fromFile) { + f_ambig++; + ambig++; + } + if (r == mt->fromRank) { + r_ambig++; + ambig++; + } + gs->onMove = CToggle(gs->onMove); + } } - - return mStr; + } + 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; + } + } +check:; + fakeMove = *gs; + execute_move(&fakeMove, mt, 0); + fakeMove.onMove = CToggle(fakeMove.onMove); + if (in_check(&fakeMove)) { + strcat(mStr, "+"); + } + return mStr; } |