| 32 #include <stdlib.h> |
32 #include <stdlib.h> |
| 33 #include <stdio.h> |
33 #include <stdio.h> |
| 34 |
34 |
| 35 static size_t fen_pieces(char *str, GameState *gamestate) { |
35 static size_t fen_pieces(char *str, GameState *gamestate) { |
| 36 size_t i = 0; |
36 size_t i = 0; |
| 37 for (int row = 7 ; row >= 0 ; row--) { |
37 Rank rank = 7; |
| |
38 do { |
| 38 unsigned int skip = 0; |
39 unsigned int skip = 0; |
| 39 for (int file = 0 ; file < 8 ; file++) { |
40 for (File file = 0 ; file < 8 ; file++) { |
| 40 if (gamestate->board[row][file]) { |
41 if (gamestate->board[rank][file]) { |
| 41 if (skip > 0) { |
42 if (skip > 0) { |
| 42 str[i++] = '0'+skip; |
43 str[i++] = '0'+skip; |
| 43 skip = 0; |
44 skip = 0; |
| 44 } |
45 } |
| 45 switch (piece_at(gamestate, row, file)) { |
46 switch (piece_at(gamestate, rank, file)) { |
| 46 case WHITE|KING: str[i++] = 'K'; break; |
47 case WHITE|KING: str[i++] = 'K'; break; |
| 47 case WHITE|QUEEN: str[i++] = 'Q'; break; |
48 case WHITE|QUEEN: str[i++] = 'Q'; break; |
| 48 case WHITE|BISHOP: str[i++] = 'B'; break; |
49 case WHITE|BISHOP: str[i++] = 'B'; break; |
| 49 case WHITE|KNIGHT: str[i++] = 'N'; break; |
50 case WHITE|KNIGHT: str[i++] = 'N'; break; |
| 50 case WHITE|ROOK: str[i++] = 'R'; break; |
51 case WHITE|ROOK: str[i++] = 'R'; break; |
| 61 } |
62 } |
| 62 } |
63 } |
| 63 if (skip > 0) { |
64 if (skip > 0) { |
| 64 str[i++] = '0'+skip; |
65 str[i++] = '0'+skip; |
| 65 } |
66 } |
| 66 if (row > 0) { |
67 if (rank > 0) { |
| 67 str[i++] = '/'; |
68 str[i++] = '/'; |
| 68 } |
69 } |
| 69 } |
70 } while (rank-- > 0); |
| 70 |
71 |
| 71 return i; |
72 return i; |
| 72 } |
73 } |
| 73 |
74 |
| 74 static size_t fen_color(char *str, GameState *gamestate) { |
75 static size_t fen_color(char *str, GameState *gamestate) { |
| 75 str[0] = current_color(gamestate) == WHITE ? 'w' : 'b'; |
76 str[0] = current_color(gamestate) == WHITE ? 'w' : 'b'; |
| 76 return 1; |
77 return 1; |
| 77 } |
78 } |
| 78 |
79 |
| 79 static bool fen_castling_chkmoved(GameState *gamestate, |
80 static bool fen_castling_chkmoved(GameState *gamestate, |
| 80 uint8_t row, uint8_t file) { |
81 Rank rank, File file) { |
| 81 |
82 |
| 82 for (unsigned i = 0 ; i < gamestate->movecount ; i++) { |
83 for (unsigned i = 0 ; i < gamestate->movecount ; i++) { |
| 83 if (gamestate->moves[i].fromfile == file |
84 if (gamestate->moves[i].fromfile == file |
| 84 && gamestate->moves[i].fromrow == row) { |
85 && gamestate->moves[i].fromrank == rank) { |
| 85 return true; |
86 return true; |
| 86 } |
87 } |
| 87 } |
88 } |
| 88 |
89 |
| 89 return false; |
90 return false; |
| 90 } |
91 } |
| 91 |
92 |
| 92 static size_t fen_castling(char *str, GameState *gamestate) { |
93 static size_t fen_castling(char *str, GameState *gamestate) { |
| 93 bool K, Q, k, q; |
94 bool K, Q, k, q; |
| 94 |
95 |
| 95 if (fen_castling_chkmoved(gamestate, rowidx('1'), fileidx('e'))) { |
96 if (fen_castling_chkmoved(gamestate, rankidx('1'), fileidx('e'))) { |
| 96 K = Q = false; |
97 K = Q = false; |
| 97 } else { |
98 } else { |
| 98 K = !fen_castling_chkmoved(gamestate, rowidx('1'), fileidx('h')); |
99 K = !fen_castling_chkmoved(gamestate, rankidx('1'), fileidx('h')); |
| 99 Q = !fen_castling_chkmoved(gamestate, rowidx('1'), fileidx('a')); |
100 Q = !fen_castling_chkmoved(gamestate, rankidx('1'), fileidx('a')); |
| 100 } |
101 } |
| 101 if (fen_castling_chkmoved(gamestate, rowidx('8'), fileidx('e'))) { |
102 if (fen_castling_chkmoved(gamestate, rankidx('8'), fileidx('e'))) { |
| 102 k = q = false; |
103 k = q = false; |
| 103 } else { |
104 } else { |
| 104 k = !fen_castling_chkmoved(gamestate, rowidx('8'), fileidx('h')); |
105 k = !fen_castling_chkmoved(gamestate, rankidx('8'), fileidx('h')); |
| 105 q = !fen_castling_chkmoved(gamestate, rowidx('8'), fileidx('a')); |
106 q = !fen_castling_chkmoved(gamestate, rankidx('8'), fileidx('a')); |
| 106 } |
107 } |
| 107 |
108 |
| 108 size_t i = 0; |
109 size_t i = 0; |
| 109 if (K) str[i++] = 'K'; |
110 if (K) str[i++] = 'K'; |
| 110 if (Q) str[i++] = 'Q'; |
111 if (Q) str[i++] = 'Q'; |
| 120 str[0] = '-'; |
121 str[0] = '-'; |
| 121 |
122 |
| 122 for (int file = 0 ; file < 8 ; file++) { |
123 for (int file = 0 ; file < 8 ; file++) { |
| 123 if (enpassant_threat_exists(gamestate, 3, file)) { |
124 if (enpassant_threat_exists(gamestate, 3, file)) { |
| 124 str[0] = filechr(file); |
125 str[0] = filechr(file); |
| 125 str[1] = rowchr(2); |
126 str[1] = rankchr(2); |
| 126 } |
127 } |
| 127 if (enpassant_threat_exists(gamestate, 4, file)) { |
128 if (enpassant_threat_exists(gamestate, 4, file)) { |
| 128 str[0] = filechr(file); |
129 str[0] = filechr(file); |
| 129 str[1] = rowchr(5); |
130 str[1] = rankchr(5); |
| 130 } |
131 } |
| 131 } |
132 } |
| 132 |
133 |
| 133 return str[0] == '-' ? 1 : 2; |
134 return str[0] == '-' ? 1 : 2; |
| 134 } |
135 } |