implemented FEN

Wed, 26 Aug 2015 14:46:42 +0200

author
Mike Becker <universe@uap-core.de>
date
Wed, 26 Aug 2015 14:46:42 +0200
changeset 54
eef745ba3774
parent 53
78b580bfde33
child 55
54ea19938d57

implemented FEN

src/chess/pgn.c file | annotate | diff | comparison | revisions
src/chess/pgn.h file | annotate | diff | comparison | revisions
src/game.c file | annotate | diff | comparison | revisions
     1.1 --- a/src/chess/pgn.c	Wed Aug 26 12:59:30 2015 +0200
     1.2 +++ b/src/chess/pgn.c	Wed Aug 26 14:46:42 2015 +0200
     1.3 @@ -194,3 +194,158 @@
     1.4      
     1.5      return bytes;
     1.6  }
     1.7 +
     1.8 +static size_t fen_pieces(char *str, GameState *gamestate) {
     1.9 +    size_t i = 0;
    1.10 +    for (int row = 7 ; row >= 0 ; row--) {
    1.11 +        unsigned int skip = 0;
    1.12 +        for (int file = 0 ; file < 8 ; file++) {
    1.13 +            if (gamestate->board[row][file]) {
    1.14 +                if (skip > 0) {
    1.15 +                    str[i++] = '0'+skip;
    1.16 +                    skip = 0;
    1.17 +                }
    1.18 +                switch (gamestate->board[row][file] & ~ENPASSANT_THREAT) {
    1.19 +                case WHITE|KING: str[i++] = 'K'; break;
    1.20 +                case WHITE|QUEEN: str[i++] = 'Q'; break;
    1.21 +                case WHITE|BISHOP: str[i++] = 'B'; break;
    1.22 +                case WHITE|KNIGHT: str[i++] = 'N'; break;
    1.23 +                case WHITE|ROOK: str[i++] = 'R'; break;
    1.24 +                case WHITE|PAWN: str[i++] = 'P'; break;
    1.25 +                case BLACK|KING: str[i++] = 'k'; break;
    1.26 +                case BLACK|QUEEN: str[i++] = 'q'; break;
    1.27 +                case BLACK|BISHOP: str[i++] = 'b'; break;
    1.28 +                case BLACK|KNIGHT: str[i++] = 'n'; break;
    1.29 +                case BLACK|ROOK: str[i++] = 'r'; break;
    1.30 +                case BLACK|PAWN: str[i++] = 'p'; break;
    1.31 +                }
    1.32 +            } else {
    1.33 +                skip++;
    1.34 +            }
    1.35 +        }
    1.36 +        if (skip > 0) {
    1.37 +            str[i++] = '0'+skip;
    1.38 +        }
    1.39 +        if (row > 0) {
    1.40 +            str[i++] = '/';
    1.41 +        }
    1.42 +    }
    1.43 +    
    1.44 +    return i;
    1.45 +}
    1.46 +
    1.47 +static size_t fen_color(char *str, GameState *gamestate) {
    1.48 +    uint8_t color = opponent_color(gamestate->lastmove ?
    1.49 +        (gamestate->lastmove->move.piece & COLOR_MASK) : BLACK);
    1.50 +    
    1.51 +    str[0] = color == WHITE ? 'w' : 'b';
    1.52 +    
    1.53 +    return 1;
    1.54 +}
    1.55 +
    1.56 +static _Bool fen_castling_chkmoved(GameState *gamestate,
    1.57 +    uint8_t row, uint8_t file) {
    1.58 +    
    1.59 +    MoveList *ml = gamestate->movelist;
    1.60 +    while (ml) {
    1.61 +        if (ml->move.fromfile == file && ml->move.fromrow == row) {
    1.62 +            return 1;
    1.63 +        }
    1.64 +        ml = ml->next;
    1.65 +    }
    1.66 +    
    1.67 +    return 0;
    1.68 +}
    1.69 +
    1.70 +static size_t fen_castling(char *str, GameState *gamestate) {
    1.71 +    _Bool K, Q, k, q;
    1.72 +    
    1.73 +    if (fen_castling_chkmoved(gamestate, rowidx('1'), fileidx('e'))) {
    1.74 +        K = Q = 0;
    1.75 +    } else {
    1.76 +        K = !fen_castling_chkmoved(gamestate, rowidx('1'), fileidx('h'));
    1.77 +        Q = !fen_castling_chkmoved(gamestate, rowidx('1'), fileidx('a'));
    1.78 +    }
    1.79 +    if (fen_castling_chkmoved(gamestate, rowidx('8'), fileidx('e'))) {
    1.80 +        k = q = 0;
    1.81 +    } else {
    1.82 +        k = !fen_castling_chkmoved(gamestate, rowidx('8'), fileidx('h'));
    1.83 +        q = !fen_castling_chkmoved(gamestate, rowidx('8'), fileidx('a'));
    1.84 +    }
    1.85 +    
    1.86 +    size_t i = 0;
    1.87 +    if (K) str[i++] = 'K';
    1.88 +    if (Q) str[i++] = 'Q';
    1.89 +    if (k) str[i++] = 'k';
    1.90 +    if (q) str[i++] = 'q';
    1.91 +    if (!i) str[i++] = '-';
    1.92 +    
    1.93 +    return i;
    1.94 +}
    1.95 +
    1.96 +static size_t fen_enpassant(char *str, GameState *gamestate) {
    1.97 +    
    1.98 +    str[0] = '-'; str[1] = '\0';
    1.99 +    
   1.100 +    for (int file = 0 ; file < 8 ; file++) {
   1.101 +        if (gamestate->board[3][file] & ENPASSANT_THREAT) {
   1.102 +            str[0] = filechr(file);
   1.103 +            str[1] = rowchr(2);
   1.104 +        }
   1.105 +        if (gamestate->board[4][file] & ENPASSANT_THREAT) {
   1.106 +            str[0] = filechr(file);
   1.107 +            str[1] = rowchr(5);
   1.108 +        }
   1.109 +    }
   1.110 +    
   1.111 +    return str[0] == '-' ? 1 : 2;
   1.112 +}
   1.113 +
   1.114 +static size_t fen_halfmove(char *str, GameState *gamestate) {
   1.115 +    
   1.116 +    unsigned int i = 0;
   1.117 +    for (MoveList *move = gamestate->movelist ; move ; move = move->next) {
   1.118 +        if (move->move.capture || (move->move.piece & PIECE_MASK) == PAWN) {
   1.119 +            i = 0;
   1.120 +        } else {
   1.121 +            i++;
   1.122 +        }
   1.123 +    }
   1.124 +    
   1.125 +    char m[8];
   1.126 +    size_t len = sprintf(m, "%u", i);
   1.127 +    memcpy(str, m, len);
   1.128 +    
   1.129 +    return len;
   1.130 +}
   1.131 +
   1.132 +static size_t fen_movenr(char *str, GameState *gamestate) {
   1.133 +    
   1.134 +    MoveList *move = gamestate->movelist;
   1.135 +    unsigned int i = 1;
   1.136 +    while (move) {
   1.137 +        i++;
   1.138 +        move = move->next;
   1.139 +    }
   1.140 +    
   1.141 +    char m[8];
   1.142 +    size_t len = sprintf(m, "%u", i);
   1.143 +    memcpy(str, m, len);
   1.144 +    
   1.145 +    return len;
   1.146 +}
   1.147 +
   1.148 +void compute_fen(char *str, GameState *gamestate) {
   1.149 +    str += fen_pieces(str, gamestate);
   1.150 +    *str = ' '; str++;
   1.151 +    str += fen_color(str, gamestate);
   1.152 +    *str = ' '; str++;
   1.153 +    str += fen_castling(str, gamestate);
   1.154 +    *str = ' '; str++;
   1.155 +    str += fen_enpassant(str, gamestate);
   1.156 +    *str = ' '; str++;
   1.157 +    str += fen_halfmove(str, gamestate);
   1.158 +    *str = ' '; str++;
   1.159 +    str += fen_movenr(str, gamestate);
   1.160 +    str[0] = '\0';
   1.161 +}
     2.1 --- a/src/chess/pgn.h	Wed Aug 26 12:59:30 2015 +0200
     2.2 +++ b/src/chess/pgn.h	Wed Aug 26 14:46:42 2015 +0200
     2.3 @@ -37,9 +37,10 @@
     2.4  #ifdef	__cplusplus
     2.5  extern "C" {
     2.6  #endif
     2.7 -    
     2.8 +
     2.9  int read_pgn(FILE *stream, GameState *gamestate, GameInfo *gameinfo);
    2.10  size_t write_pgn(FILE* stream, GameState *gamestate, GameInfo *gameinfo);
    2.11 +void compute_fen(char *str, GameState *gamestate);
    2.12  
    2.13  #ifdef	__cplusplus
    2.14  }
     3.1 --- a/src/game.c	Wed Aug 26 12:59:30 2015 +0200
     3.2 +++ b/src/game.c	Wed Aug 26 14:46:42 2015 +0200
     3.3 @@ -72,6 +72,10 @@
     3.4  }
     3.5  
     3.6  static void draw_board(GameState *gamestate, uint8_t perspective) {
     3.7 +    char fen[90];
     3.8 +    compute_fen(fen, gamestate);
     3.9 +    mvaddstr(0, 0, fen);
    3.10 +    
    3.11      for (uint8_t y = 0 ; y < 8 ; y++) {
    3.12          for (uint8_t x = 0 ; x < 8 ; x++) {
    3.13              uint8_t col = gamestate->board[y][x] & COLOR_MASK;
    3.14 @@ -109,7 +113,7 @@
    3.15      
    3.16      /* move log */
    3.17      // TODO: introduce window to avoid bugs with a long move log
    3.18 -    uint8_t logy = 0;
    3.19 +    uint8_t logy = 1;
    3.20      const uint8_t logx = boardx + 30;
    3.21      int logi = 1;
    3.22      MoveList *logelem = gamestate->movelist;

mercurial