Wed, 26 Aug 2015 14:46:42 +0200
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;