Introduction
Introduction Statistics Contact Development Disclaimer Help
fen_to_tty.c - chess-puzzles - chess puzzle book generator
git clone git://git.codemadness.org/chess-puzzles
Log
Files
Refs
README
LICENSE
---
fen_to_tty.c (7357B)
---
1 /* TODO: option to flip board? */
2
3 #include <ctype.h>
4 #include <stdio.h>
5 #include <string.h>
6
7 static char board[8][8];
8 static char highlight[8][8];
9
10 static int side_to_move = 'w'; /* default: white to move */
11 static int white_can_castle[2] = { 0, 0 }; /* allow king side, allow que…
12 static int black_can_castle[2] = { 0, 0 }; /* allow king side, allow que…
13
14 static const int showcoords = 1; /* config: show board coordinates? */
15
16 #define SETFGCOLOR(r,g,b) printf("\x1b[38;2;%d;%d;%dm", r, g, b)
17 #define SETBGCOLOR(r,g,b) printf("\x1b[48;2;%d;%d;%dm", r, g, b)
18
19 int
20 isvalidsquare(int x, int y)
21 {
22 return !(x < 0 || x >= 8 || y < 0 || y >= 8);
23 }
24
25 /* place a piece, if possible */
26 void
27 place(int piece, int x, int y)
28 {
29 if (!isvalidsquare(x, y))
30 return;
31
32 board[y][x] = piece;
33 }
34
35 /* get piece, if possible */
36 int
37 getpiece(int x, int y)
38 {
39 if (!isvalidsquare(x, y))
40 return 0;
41 return board[y][x];
42 }
43
44 int
45 squaretoxy(const char *s, int *x, int *y)
46 {
47 if (*s >= 'a' && *s <= 'h' &&
48 *(s + 1) >= '1' && *(s + 1) <= '8') {
49 *x = *s - 'a';
50 *y = '8' - *(s + 1);
51 return 1;
52 }
53 return 0;
54 }
55
56 void
57 highlightmove(int x1, int y1, int x2, int y2)
58 {
59 if (isvalidsquare(x1, y1))
60 highlight[y1][x1] = 1;
61
62 if (isvalidsquare(x2, y2))
63 highlight[y2][x2] = 1;
64 }
65
66 void
67 showpiece(int c)
68 {
69 const char *s = "";
70
71 /* simple or use unicode character */
72 #if 0
73 putchar(c);
74 return;
75 #endif
76
77 switch (c) {
78 case 'K': s = "♔"; break;
79 case 'Q': s = "♕"; break;
80 case 'R': s = "♖"; break;
81 case 'B': s = "♗"; break;
82 case 'N': s = "♘"; break;
83 case 'P': s = "♙"; break;
84 case 'k': s = "♚"; break;
85 case 'q': s = "♛"; break;
86 case 'r': s = "♜"; break;
87 case 'b': s = "♝"; break;
88 case 'n': s = "♞"; break;
89 case 'p': s = "♟"; break;
90 }
91
92 if (*s)
93 fputs(s, stdout);
94 }
95
96 void
97 showboardfen(void)
98 {
99 int x, y, piece, skip = 0;
100
101 for (y = 0; y < 8; y++) {
102 if (y > 0)
103 putchar('/');
104 skip = 0;
105 for (x = 0; x < 8; x++) {
106 piece = getpiece(x, y);
107 if (piece) {
108 if (skip)
109 putchar(skip + '0');
110 putchar(piece);
111 skip = 0;
112 } else {
113 skip++;
114 }
115 }
116 if (skip)
117 putchar(skip + '0');
118 }
119
120 /* ? TODO: detect en passant, invalid castling etc? */
121 }
122
123 /* show board */
124 void
125 showboard(void)
126 {
127 int *color;
128 int border[] = { 0x70, 0x49, 0x2d };
129 int darksquare[] = { 0xb5, 0x88, 0x63 };
130 int lightsquare[] = { 0xf0, 0xd9, 0xb5 };
131 int darksquarehi[] = { 0xaa, 0xa2, 0x3a };
132 int lightsquarehi[] = { 0xcd, 0xd2, 0x6a };
133 int x, y, piece;
134
135 printf("Board FEN:\n");
136 showboardfen();
137 printf("\n\n");
138
139 SETFGCOLOR(0x00, 0x00, 0x00);
140
141 color = border;
142 SETBGCOLOR(color[0], color[1], color[2]);
143 SETFGCOLOR(0xff, 0xff, 0xff);
144 fputs(" ", stdout);
145 printf("\x1b[0m"); /* reset */
146 SETFGCOLOR(0x00, 0x00, 0x00);
147 putchar('\n');
148
149 for (y = 0; y < 8; y++) {
150 color = border;
151 SETBGCOLOR(color[0], color[1], color[2]);
152 SETFGCOLOR(0xff, 0xff, 0xff);
153 fputs(" ", stdout);
154
155 for (x = 0; x < 8; x++) {
156 if (x % 2 == 0) {
157 if (y % 2 == 0)
158 color = highlight[y][x] ? lights…
159 else
160 color = highlight[y][x] ? darksq…
161 } else {
162 if (y % 2 == 0)
163 color = highlight[y][x] ? darksq…
164 else
165 color = highlight[y][x] ? lights…
166 }
167 SETBGCOLOR(color[0], color[1], color[2]);
168
169 fputs(" ", stdout);
170 piece = getpiece(x, y);
171 if (piece) {
172 if (piece >= 'A' && piece <= 'Z')
173 SETFGCOLOR(0xff, 0xff, 0xff);
174 else
175 SETFGCOLOR(0x00, 0x00, 0x00);
176 /* workaround: use black chess symbol, b…
177 is filled and better visible */
178 showpiece(tolower(piece));
179 } else {
180 fputs(" ", stdout);
181 }
182 fputs(" ", stdout);
183 }
184 printf("\x1b[0m"); /* reset */
185
186 color = border;
187 SETBGCOLOR(color[0], color[1], color[2]);
188 SETFGCOLOR(0xff, 0xff, 0xff);
189 if (showcoords) {
190 putchar(' ');
191 putchar('8' - y);
192 putchar(' ');
193 } else {
194 fputs(" ", stdout);
195 }
196
197 printf("\x1b[0m"); /* reset */
198 SETFGCOLOR(0x00, 0x00, 0x00);
199 putchar('\n');
200 }
201 color = border;
202 SETBGCOLOR(color[0], color[1], color[2]);
203 SETFGCOLOR(0xff, 0xff, 0xff);
204 if (showcoords)
205 fputs(" a b c d e f g h ", stdout);
206 else
207 fputs(" ", stdout);
208 printf("\x1b[0m"); /* reset */
209 printf("\n");
210 printf("\x1b[0m"); /* reset */
211
212 #if 0
213 if (side_to_move == 'w') {
214 fputs("White to move\n", stdout);
215 } else if (side_to_move == 'b')
216 fputs("Black to move\n", stdout);
217
218 if (white_can_castle[0])
219 fputs("White can castle king side\n", stdout);
220 if (white_can_castle[1])
221 fputs("White can castle queen side\n", stdout);
222 if (black_can_castle[0])
223 fputs("Black can castle king side\n", stdout);
224 if (black_can_castle[1])
225 fputs("Black can castle queen side\n", stdout);
226 #endif
227 }
228
229 int
230 main(int argc, char *argv[])
231 {
232 const char *fen, *moves, *s;
233 int x, y, x2, y2, field, piece;
234 char pieces[] = "PNBRQKpnbrqk", square[3];
235
236 if (argc != 3) {
237 fprintf(stderr, "usage: %s <FEN> <moves>\n", argv[0]);
238 return 1;
239 }
240
241 fen = argv[1];
242 moves = argv[2];
243
244 /* initial board state, FEN format */
245 x = y = field = 0;
246 for (s = fen; *s; s++) {
247 /* next field, fields are: piece placement data, active …
248 Castling availability, En passant target square,
249 Halfmove clock, Fullmove number */
250 if (*s == ' ') {
251 field++;
252 continue;
253 }
254
255 switch (field) {
256 case 0: /* piece placement data */
257 /* skip square */
258 if (*s >= '1' && *s <= '9') {
259 x += (*s - '0');
260 continue;
261 }
262 /* next rank */
263 if (*s == '/') {
264 x = 0;
265 y++;
266 continue;
267 }
268 /* is piece? place it */
269 if (strchr(pieces, *s))
270 place(*s, x++, y);
271 break;
272 case 1: /* active color */
273 if (*s == 'w' || *s == 'b')
274 side_to_move = *s;
275 break;
276 case 2: /* castling availability */
277 if (*s == '-') {
278 white_can_castle[0] = 0;
279 white_can_castle[1] = 0;
280 black_can_castle[0] = 0;
281 black_can_castle[1] = 0;
282 } else if (*s == 'K') {
283 white_can_castle[0] = 1;
284 } else if (*s == 'Q') {
285 white_can_castle[1] = 1;
286 } else if (*s == 'k') {
287 black_can_castle[0] = 1;
288 } else if (*s == 'q') {
289 black_can_castle[1] = 1;
290 }
291 break;
292 case 3: /* TODO: en-passant square, rest of the fields */
293 break;
294 }
295 /* TODO: parse which side to move, en-passant, etc */
296 }
297
298 /* process moves */
299 square[2] = '\0';
300 x = y = x2 = y2 = -1;
301 for (s = moves; *s; s++) {
302 if (*s == ' ')
303 continue;
304 if ((*s >= 'a' && *s <= 'h') &&
305 (*(s + 1) >= '1' && *(s + 1) <= '8') &&
306 (*(s + 2) >= 'a' && *(s + 2) <= 'h') &&
307 (*(s + 3) >= '1' && *(s + 3) <= '8')) {
308 square[0] = *s;
309 square[1] = *(s + 1);
310
311 s += 2;
312 squaretoxy(square, &x, &y);
313 piece = getpiece(x, y);
314
315 place(0, x, y); /* clear square */
316
317 /* place piece at new location */
318 square[0] = *s;
319 square[1] = *(s + 1);
320 squaretoxy(square, &x2, &y2);
321 place(piece, x2, y2);
322 s += 2;
323
324 /* possible promotion? (queen, knight, bishop) */
325 if (*s == 'q' || *s == 'n' || *s == 'b') {
326 if (side_to_move == 'w')
327 piece = toupper(*s);
328 else
329 piece = *s;
330 place(piece, x2, y2);
331 s++;
332 }
333
334 /* switch which side it is to move */
335 side_to_move = side_to_move == 'b' ? 'w' : 'b';
336 }
337 }
338 /* highlight last move */
339 highlightmove(x, y, x2, y2);
340
341 showboard();
342
343 printf("\x1b[0m"); /* reset */
344
345 return 0;
346 }
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.