git.haldean.org grandmaster / 2996dc4
don't calculate FEN/PGN for every move, until needed haldean 8 months ago
10 changed file(s) with 45 addition(s) and 64 deletion(s). Raw diff Collapse all Expand all
3838 if (game == NULL)
3939 return NULL;
4040 move = game->current->move;
41 res = board_to_json(move->post_board);
41 res = move_to_json(move);
4242 json_object_set_new(
4343 res, "termination",
4444 json_string(termination_str(game->termination)));
116116 int8_t passant_file;
117117 /* ply index is the number of plys that have been played, inclusive. */
118118 uint16_t ply_index;
119 /* PGN is the PGN for the game played up until this point. */
120 char *pgn;
121 /* FEN is the board state encoded in Forsyth-Edwards notation. */
122 char *fen;
123119 /* the available termination state for this move. Note that there are
124120 * multiple "the game is not over" "termination" states: both
125121 * AVAILABLE_MOVE and AVAILABLE_STALEMATE are valid values here.
191187 /* Convert a move to JSON. */
192188 json_t *move_to_json(const struct move *);
193189
194 /* Convert a board to JSON. */
195 json_t *board_to_json(const struct board *board);
196
197190 /* Convert a move to FEN. */
198191 char *move_to_fen(const struct move *);
199192
3636 } while (0);
3737 #endif
3838
39 /* Creates a deep copy of the given board struct. */
40 struct board *copy_board(const struct board *);
39 /* Creates a deep copy of the given board struct into the first, preallocated
40 * struct. */
41 void copy_board(struct board *, const struct board *);
4142
4243 void read_location(const char *str, struct position *result);
4344
4950 void print_move(const struct move *);
5051
5152 /* Convert a board to JSON. */
52 json_t *board_to_json(const struct board *);
53 json_t *board_to_json(const struct board *, const struct move *);
5354
5455 /* Blindly apply movement represented by start and end points, disregarding the
5556 * validity of the move itself. */
6768 /* Returns a move that contains the root of the full game tree. */
6869 void get_root(struct move *out);
6970
70 /* Free a board struct. */
71 void free_board(struct board *board);
72
7371 /* Free a move struct, leaving its parent move untouched. */
7472 void free_move(struct move *move);
7573
7977 /* Creates PGN for a given move. In most cases, callers should use
8078 * move->post_board->pgn instead; this is what is used to populate the pgn
8179 * field on the board struct. */
82 char *create_pgn(struct move *move);
80 char *create_pgn(const struct move *move);
8381
8482 /* Convert a board struct to Forsythe-Edwards Notation. */
85 char *board_to_fen(struct board *board, color_t player);
83 char *board_to_fen(const struct board *board, color_t player);
8684
8785 #endif
7171 if (is_movement_valid(&test_move)
7272 && n < MAX_PIECE_COUNT)
7373 access[n++] = test_move.start;
74 free_board(test_move.post_board);
75 test_move.post_board = NULL;
7674 }
7775 }
76 free(test_move.post_board);
7877 }
7978
8079 void
118117 if (is_movement_valid(&test_move))
119118 {
120119 move->start = test_move.start;
121 free_board(test_move.post_board);
120 free(test_move.post_board);
122121 return;
123122 }
124 free_board(test_move.post_board);
125 test_move.post_board = NULL;
126123 }
127124 }
125 free(test_move.post_board);
128126 }
129127
130128 bool
1919 #include "grandmaster/core.h"
2020 #include "grandmaster/internal.h"
2121
22 #include <assert.h>
2223 #include <stdbool.h>
2324 #include <stdio.h>
2425 #include <stdlib.h>
109110 rook_start_file = is_kingside ? 7 : 0;
110111 rook_end_file = is_kingside ? 5 : 3;
111112
112 out->post_board = copy_board(last_move->post_board);
113 out->post_board = calloc(1, sizeof out->post_board);
114 assert(out->post_board != NULL);
115 copy_board(out->post_board, last_move->post_board);
113116
114117 memset(
115118 out->post_board->access, NO_POS, sizeof out->post_board->access);
224227
225228 if (is_passant)
226229 {
227 out->post_board = copy_board(last_move->post_board);
230 out->post_board = calloc(1, sizeof out->post_board);
231 assert(out->post_board != NULL);
232 copy_board(out->post_board, last_move->post_board);
228233
229234 /* move the pawn */
230235 out->post_board->board[out->end.rank][out->end.file] =
447452 }
448453 else
449454 {
450 result->post_board->fifty_move_counter =
451 result->parent->post_board->fifty_move_counter + 1;
455 result->post_board->fifty_move_counter++;
452456 }
453457
454458 build_access_map(result);
455459
456460 result->post_board->ply_index =
457461 1 + result->parent->post_board->ply_index;
458 result->post_board->pgn = create_pgn(result);
459 result->post_board->fen = move_to_fen(result);
460462
461463 if (in_checkmate(result, opposite(result->player)))
462464 {
3030 | BLACK_KINGSIDE | BLACK_QUEENSIDE;
3131 b->passant_file = NO_PASSANT;
3232 b->ply_index = 0;
33 b->pgn = strdup("");
3433
3534 b->board[0][0] = (struct piece){ .color = WHITE, .piece_type = ROOK };
3635 b->board[0][1] =
7877 b->draws = DRAW_NONE;
7978 b->in_check = false;
8079 b->fifty_move_counter = 0;
81
82 b->fen = board_to_fen(b, BLACK);
8380 }
8481
8582 void
8784 {
8885 assert(m->parent->post_board != NULL);
8986 if (m->post_board == NULL)
90 {
91 m->post_board = copy_board(m->parent->post_board);
92 m->post_board->board[m->end.rank][m->end.file] =
93 m->post_board->board[m->start.rank][m->start.file];
94 m->post_board->board[m->start.rank][m->start.file] =
95 (struct piece){ .color = 0, .piece_type = 0 };
96 }
87 m->post_board = calloc(1, sizeof(struct board));
88 copy_board(m->post_board, m->parent->post_board);
89 m->post_board->board[m->end.rank][m->end.file] =
90 m->post_board->board[m->start.rank][m->start.file];
91 m->post_board->board[m->start.rank][m->start.file] =
92 (struct piece){ .color = 0, .piece_type = 0 };
9793 }
9894
9995 bool
121117 return true;
122118 }
123119
124 struct board *
125 copy_board(const struct board *b)
120 void
121 copy_board(struct board *res, const struct board *b)
126122 {
127 struct board *res;
128 res = calloc(1, sizeof(struct board));
129 assert(res != NULL);
130123 memcpy(res, b, sizeof(struct board));
131 res->pgn = strdup(b->pgn);
132 res->fen = strdup(b->fen);
133 return res;
134124 }
4545 #endif
4646
4747 char *
48 board_to_fen(struct board *board, color_t player)
48 board_to_fen(const struct board *board, color_t player)
4949 {
5050 char *fen;
51 struct piece *p;
51 const struct piece *p;
5252 int i;
5353 int rank;
5454 int file;
145145 }
146146
147147 json_t *
148 board_to_json(const struct board *board)
148 board_to_json(const struct board *board, const struct move *move)
149149 {
150150 int rank;
151151 int file;
152152 int i;
153153 const struct position *a;
154154 const struct piece *p;
155 char *pgn;
156 char *fen;
155157 json_t *board_root;
156158 json_t *board_array;
157159 json_t *map_array;
219221 }
220222 json_set(board_root, "access_map", map_array);
221223
224 pgn = create_pgn(move);
225 json_set(board_root, "pgn", json_string(pgn));
226 free(pgn);
227
228 fen = board_to_fen(board, move->player);
229 json_set(board_root, "fen", json_string(fen));
230 free(fen);
231
222232 json_set(board_root, "ply_index", json_integer(board->ply_index));
223 json_set(board_root, "pgn", json_string(board->pgn));
224 json_set(board_root, "fen", json_string(board->fen));
225233
226234 json_set(
227235 board_root, "termination",
252260
253261 if (move->post_board != NULL)
254262 {
255 temp = board_to_json(move->post_board);
263 temp = board_to_json(move->post_board, move);
256264 }
257265 else
258266 {
171171 }
172172
173173 char *
174 create_pgn(struct move *move)
174 create_pgn(const struct move *move)
175175 {
176176 char *base;
177177 char *res;
180180
181181 /* if we're the root node, there's no need to include us in the PGN. */
182182 if (move->algebraic == NULL)
183 return "";
183 return strdup("");
184184
185185 if (move->parent != NULL)
186186 {
187187 base = create_pgn(move->parent);
188188 base_len = strlen(base);
189 if (base_len == 0)
190 free(base);
189191 }
190192 else
191193 {
183183 }
184184
185185 void
186 free_board(struct board *b)
187 {
188 if (b->pgn != NULL)
189 free(b->pgn);
190 if (b->fen != NULL)
191 free(b->fen);
192 free(b);
193 }
194
195 void
196186 free_move_tree(struct move *move)
197187 {
198188 if (move->parent != NULL)
204194 free_move(struct move *move)
205195 {
206196 if (move->post_board != NULL)
207 free_board(move->post_board);
197 free(move->post_board);
208198 if (move->algebraic != NULL)
209199 free(move->algebraic);
210200 free(move);