fork download
  1. #include <stdio.h>
  2.  
  3. // FEN dedug positions
  4. char start_position[] = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
  5. char tricky_position[] = "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1";
  6.  
  7. // piece encoding
  8. enum pieces {e, P, N, B, R, Q, K, p, n, b, r, q, k, o};
  9.  
  10. // square encoding
  11. enum squares {
  12. a8 = 0, b8, c8, d8, e8, f8, g8, h8,
  13. a7 = 16, b7, c7, d7, e7, f7, g7, h7,
  14. a6 = 32, b6, c6, d6, e6, f6, g6, h6,
  15. a5 = 48, b5, c5, d5, e5, f5, g5, h5,
  16. a4 = 64, b4, c4, d4, e4, f4, g4, h4,
  17. a3 = 80, b3, c3, d3, e3, f3, g3, h3,
  18. a2 = 96, b2, c2, d2, e2, f2, g2, h2,
  19. a1 = 112, b1, c1, d1, e1, f1, g1, h1, no_sq
  20. };
  21.  
  22. // castling binary representation
  23. //
  24. // bin dec
  25. // 0001 1 white king can castle to the king side
  26. // 0010 2 white king can castle to the queen side
  27. // 0100 4 black king can castle to the king side
  28. // 1000 8 black king can castle to the queen side
  29. //
  30. // examples
  31. // 1111 both sides an castle both directions
  32. // 1001 black king => queen side
  33. // white king => king side
  34.  
  35. // castling writes
  36. enum castling { KC = 1, QC = 2, kc = 4, qc = 8 };
  37.  
  38. // sides to move
  39. enum sides { white, black };
  40.  
  41. // ascii pieces
  42. char ascii_pieces[] = ".PNBRQKpnbrqk";
  43.  
  44. // unicode pieces
  45. char *unicode_pieces[] = {".", "♙", "♘", "♗", "♖", "♕", "♔", "♟︎", "♞", "♝", "♜", "♛", "♚"};
  46.  
  47. // encode ascii pieces
  48. int char_pieces[] = {
  49. ['P'] = P,
  50. ['N'] = N,
  51. ['B'] = B,
  52. ['R'] = R,
  53. ['Q'] = Q,
  54. ['K'] = K,
  55. ['p'] = p,
  56. ['n'] = n,
  57. ['b'] = b,
  58. ['r'] = r,
  59. ['q'] = q,
  60. ['k'] = k,
  61. };
  62.  
  63. // chess board representation
  64. int board[128] = {
  65. r, n, b, q, k, b, n, r, o, o, o, o, o, o, o, o,
  66. p, p, p, p, p, p, p, p, o, o, o, o, o, o, o, o,
  67. e, e, e, e, e, e, e, e, o, o, o, o, o, o, o, o,
  68. e, e, e, e, e, e, e, e, o, o, o, o, o, o, o, o,
  69. e, e, e, e, e, e, e, e, o, o, o, o, o, o, o, o,
  70. e, e, e, e, e, e, e, e, o, o, o, o, o, o, o, o,
  71. P, P, P, P, P, P, P, P, o, o, o, o, o, o, o, o,
  72. R, N, B, Q, K, B, N, R, o, o, o, o, o, o, o, o
  73. };
  74.  
  75. // side to move
  76. int side = white;
  77.  
  78. // enpassant square
  79. int enpassant = no_sq;
  80.  
  81. // castling rights (dec 15 => bin 1111 => both kings can castle to both sides)
  82. int castle = 15;
  83.  
  84. // convert board square indexes to coordinates
  85. char *square_to_coords[] = {
  86. "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8", "i8", "j8", "k8", "l8", "m8", "n8", "o8", "p8",
  87. "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7", "i7", "j7", "k7", "l7", "m7", "n7", "o7", "p7",
  88. "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6", "i6", "j6", "k6", "l6", "m6", "n6", "o6", "p6",
  89. "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5", "i5", "j5", "k5", "l5", "m5", "n5", "o5", "p5",
  90. "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4", "i4", "j4", "k4", "l4", "m4", "n4", "o4", "p4",
  91. "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", "i3", "j3", "k3", "l3", "m3", "n3", "o3", "p3",
  92. "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", "i2", "j2", "k2", "l2", "m2", "n2", "o2", "p2",
  93. "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", "i1", "j1", "k1", "l1", "m1", "n1", "o1", "p1"
  94. };
  95.  
  96. // print board
  97. void print_board()
  98. {
  99. // print new line
  100. printf("\n");
  101.  
  102. // loop over board ranks
  103. for (int rank = 0; rank < 8; rank++)
  104. {
  105. // loop over board files
  106. for (int file = 0; file < 16; file++)
  107. {
  108. // init square
  109. int square = rank * 16 + file;
  110.  
  111. // print ranks
  112. if (file == 0)
  113. printf(" %d ", 8 - rank);
  114.  
  115. // if square is on board
  116. if (!(square & 0x88))
  117. //printf("%c ", ascii_pieces[board[square]]);
  118. printf("%s ", unicode_pieces[board[square]]);
  119. }
  120.  
  121. // print new line every time new rank is encountered
  122. printf("\n");
  123. }
  124.  
  125. // print files
  126. printf("\n a b c d e f g h\n\n");
  127.  
  128. // print board stats
  129. printf(" Side: %s\n", (side == white) ? "white": "black");
  130. printf(" Castling: %c%c%c%c\n", (castle & KC) ? 'K' : '-',
  131. (castle & QC) ? 'Q' : '-',
  132. (castle & kc) ? 'k' : '-',
  133. (castle & qc) ? 'q' : '-');
  134. printf(" Enpassant: %s\n\n", square_to_coords[enpassant]);
  135. }
  136.  
  137. // reset board
  138. void reset_board()
  139. {
  140. // loop over board ranks
  141. for (int rank = 0; rank < 8; rank++)
  142. {
  143. // loop over board files
  144. for (int file = 0; file < 16; file++)
  145. {
  146. // init square
  147. int square = rank * 16 + file;
  148.  
  149. // if square is on board
  150. if (!(square & 0x88))
  151. // reset current board square
  152. board[square] = e;
  153. }
  154. }
  155.  
  156. // reset stats
  157. side = -1;
  158. castle = 0;
  159. enpassant = no_sq;
  160. }
  161.  
  162. // parse FEN
  163. void parse_fen(char *fen)
  164. {
  165. // reset board
  166. reset_board();
  167.  
  168. // loop over board ranks
  169. for (int rank = 0; rank < 8; rank++)
  170. {
  171. // loop over board files
  172. for (int file = 0; file < 16; file++)
  173. {
  174. // init square
  175. int square = rank * 16 + file;
  176.  
  177. // if square is on board
  178. if (!(square & 0x88))
  179. {
  180. // match pieces
  181. if ((*fen >= 'a' && *fen <= 'z') || (*fen >= 'A' && *fen <= 'Z'))
  182. {
  183. // set the piece on board
  184. board[square] = char_pieces[*fen];
  185.  
  186. // increment FEN pointer
  187. *fen++;
  188. }
  189.  
  190. // match empty squares
  191. if (*fen >= '0' && *fen <= '9')
  192. {
  193. // calculate offset
  194. int offset = *fen - '0';
  195.  
  196. // decrement file on empty squares
  197. if (!(board[square]))
  198. file--;
  199.  
  200. // skip empty squares
  201. file += offset;
  202.  
  203. // increment FEN pointer
  204. *fen++;
  205. }
  206.  
  207. // match end of rank
  208. if (*fen == '/')
  209. // increment FEN pointer
  210. *fen++;
  211.  
  212. }
  213. }
  214. }
  215.  
  216. // go to side parsing
  217. *fen++;
  218.  
  219. // parse side to move
  220. side = (*fen == 'w') ? white : black;
  221.  
  222. // go to castling rights parsing
  223. fen += 2;
  224.  
  225. // parse castling rights
  226. while (*fen != ' ')
  227. {
  228. switch(*fen)
  229. {
  230. case 'K': castle |= KC; break;
  231. case 'Q': castle |= QC; break;
  232. case 'k': castle |= kc; break;
  233. case 'q': castle |= qc; break;
  234. case '-': break;
  235. }
  236.  
  237. // increment pointer
  238. *fen++;
  239. }
  240.  
  241. // got to empassant square
  242. *fen++;
  243.  
  244. // parse empassant square
  245. if (*fen != '-')
  246. {
  247. // parse enpassant square's file & rank
  248. int file = fen[0] - 'a';
  249. int rank = 8 - (fen[1] - '0');
  250.  
  251. // set up enpassant square
  252. enpassant = rank * 16 + file;
  253. }
  254.  
  255. else
  256. enpassant = no_sq;
  257.  
  258. }
  259.  
  260. // main driver
  261. int main()
  262. {
  263. parse_fen("r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq g5 0 1");
  264. print_board();
  265.  
  266. return 0;
  267. }
  268.  
Success #stdin #stdout 0s 5512KB
stdin
Standard input is empty
stdout
 8  ♜ . . . ♚ . . ♜ 
 7  ♟︎ . ♟︎ ♟︎ ♛ ♟︎ ♝ . 
 6  ♝ ♞ . . ♟︎ ♞ ♟︎ . 
 5  . . . ♙ ♘ . . . 
 4  . ♟︎ . . ♙ . . . 
 3  . . ♘ . . ♕ . ♟︎ 
 2  ♙ ♙ ♙ ♗ ♗ ♙ ♙ ♙ 
 1  ♖ . . . ♔ . . ♖ 

    a b c d e f g h

    Side:     white
    Castling:  KQkq
    Enpassant:   g5