1 // This file is part of Freecell Solver. It is subject to the license terms in
2 // the COPYING.txt file found in the top-level directory of this distribution
3 // and at http://fc-solve.shlomifish.org/docs/distro/COPYING.html . No part of
4 // Freecell Solver, including this file, may be copied, modified, propagated,
5 // or distributed except according to the terms contained in the COPYING file.
6 //
7 // Copyright (c) 2000 Shlomi Fish
8 // output_to_file.h - header file for outputting a solution to a file.
9 #pragma once
10
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14
15 #include "rinutils/rinutils.h"
16 #include "freecell-solver/fcs_enums.h"
17 #include "freecell-solver/fcs_user.h"
18
19 typedef struct
20 {
21 const char *output_filename;
22 int standard_notation;
23 bool debug_iter_state_output;
24 #ifndef FC_SOLVE_IMPLICIT_PARSABLE_OUTPUT
25 bool parseable_output;
26 #endif
27 bool canonized_order_output;
28 #ifndef FC_SOLVE_IMPLICIT_T_RANK
29 bool display_10_as_t;
30 #endif
31 bool display_parent_iter_num;
32 bool display_moves;
33 bool display_states;
34 bool show_exceeded_limits;
35 bool hint_on_intract;
36 size_t iters_display_step;
37 } fc_solve_display_information_context;
38
39 static const fc_solve_display_information_context INITIAL_DISPLAY_CONTEXT = {
40 .debug_iter_state_output = false,
41 #ifndef FC_SOLVE_IMPLICIT_PARSABLE_OUTPUT
42 .parseable_output = false,
43 #endif
44 .canonized_order_output = false,
45 #ifndef FC_SOLVE_IMPLICIT_T_RANK
46 .display_10_as_t = false,
47 #endif
48 .display_parent_iter_num = false,
49 .display_moves = false,
50 .display_states = true,
51 .standard_notation = FC_SOLVE__STANDARD_NOTATION_NO,
52 .output_filename = NULL,
53 .show_exceeded_limits = false,
54 .hint_on_intract = false,
55 .iters_display_step = 1,
56 };
57
fc_solve_output_result_to_file(FILE * const output_fh,void * const instance,const int ret,const fc_solve_display_information_context * const dc_ptr)58 static inline void fc_solve_output_result_to_file(FILE *const output_fh,
59 void *const instance, const int ret,
60 const fc_solve_display_information_context *const dc_ptr)
61 {
62 const_AUTO(display_context, (*dc_ptr));
63 const bool was_solved = (ret == FCS_STATE_WAS_SOLVED);
64 const bool was_suspend = (ret == FCS_STATE_SUSPEND_PROCESS);
65 #ifdef FCS_WITH_MOVES
66 if (was_solved || (display_context.hint_on_intract && was_suspend))
67 {
68 fputs("-=-=-=-=-=-=-=-=-=-=-=-\n\n", output_fh);
69 fcs_move_t move;
70 char state_as_string[1000];
71
72 if (display_context.display_states)
73 {
74 freecell_solver_user_current_state_stringify(instance,
75 state_as_string FC_SOLVE__PASS_PARSABLE(
76 display_context.parseable_output),
77 display_context.canonized_order_output FC_SOLVE__PASS_T(
78 display_context.display_10_as_t));
79
80 fputs(state_as_string, output_fh);
81 fputs("\n\n====================\n\n", output_fh);
82 }
83
84 int move_num = 0;
85 while (freecell_solver_user_get_next_move(instance, &move) == 0)
86 {
87 if (display_context.display_moves)
88 {
89 if (display_context.display_states &&
90 display_context.standard_notation)
91 {
92 fputs("Move: ", output_fh);
93 }
94
95 freecell_solver_user_stringify_move_w_state(instance,
96 state_as_string, move, display_context.standard_notation);
97 fprintf(output_fh,
98 (display_context.standard_notation ? "%s " : "%s\n"),
99 state_as_string);
100 move_num++;
101 if (display_context.standard_notation)
102 {
103 if ((move_num % 10 == 0) || display_context.display_states)
104 {
105 putc('\n', output_fh);
106 }
107 }
108 if (display_context.display_states)
109 {
110 putc('\n', output_fh);
111 }
112 fflush(output_fh);
113 }
114
115 if (display_context.display_states)
116 {
117 freecell_solver_user_current_state_stringify(instance,
118 state_as_string FC_SOLVE__PASS_PARSABLE(
119 display_context.parseable_output),
120 display_context.canonized_order_output FC_SOLVE__PASS_T(
121 display_context.display_10_as_t));
122
123 fprintf(output_fh, "%s\n", state_as_string);
124 }
125
126 if (display_context.display_states ||
127 (!display_context.standard_notation))
128 {
129 fputs("\n====================\n\n", output_fh);
130 }
131 }
132
133 if (display_context.standard_notation &&
134 (!display_context.display_states))
135 {
136 fputs("\n\n", output_fh);
137 }
138 }
139 #endif
140 fputs((was_solved ? "This game is solveable.\n"
141 : (display_context.show_exceeded_limits && was_suspend)
142 ? "Iterations count exceeded.\n"
143 : "I could not solve this game.\n"),
144 output_fh);
145
146 fprintf(output_fh, "Total number of states checked is %ld.\n",
147 (long)freecell_solver_user_get_num_times_long(instance));
148 #ifndef FCS_DISABLE_NUM_STORED_STATES
149 fprintf(output_fh, "This scan generated %ld states.\n",
150 (long)freecell_solver_user_get_num_states_in_collection_long(instance));
151 #endif
152 }
153
154 #ifdef __cplusplus
155 }
156 #endif
157