Reveal solution functionality completed
[wordblah.git] / wordblox.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <time.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <unistd.h>
7
8 #include "wordblox.h"
9 #include "constantstrings.h"
10
11 /* export the clues to a text file */
12 void do_export_clues (Puzzle *p)
13 {
14 if (p->grid_frozen == false)
15 {
16 printf (UNFROZEN_GRID);
17 char ch = getchar ();
18 return;
19 }
20 char fname[256];
21 printf (INPUT_FILE);
22 fgets (fname, 256, stdin);
23 if (strlen(fname) == 1)
24 return;
25 char *filename = strtok (fname, "\n");
26
27 export_clues (p, filename);
28 printf (FILE_SAVED);
29 char ch = getchar ();
30 }
31
32 /* export the puzzle to a png file */
33 void do_export_puzzle (Puzzle *p)
34 {
35 if (p->grid_frozen == false)
36 {
37 printf (UNFROZEN_GRID);
38 char ch = getchar ();
39 return;
40 }
41 char fname[256];
42 printf (INPUT_FILE);
43 fgets (fname, 256, stdin);
44 if (strlen (fname) == 1)
45 return;
46 char* filename = strtok (fname, "\n");
47
48 printf (INPUT_EXPORT_ANSWERS);
49 char ans[3];
50 fgets (ans, 3, stdin);
51 bool solution;
52 solution = (toupper (ans[0]) == 'Y') ? true : false;
53
54 export_grid_image (p, filename, solution);
55 printf (FILE_SAVED);
56 char ch = getchar ();
57 }
58
59 /* reset the grid */
60 void do_reset_puzzle (Puzzle *p)
61 {
62 int grid_size = p->grid_size;
63 printf (INPUT_CONFIRM_RESET);
64 char conf[3];
65 fgets (conf, 3, stdin);
66 if (toupper (conf[0]) == 'Y')
67 init_puzzle (p, grid_size);
68
69 print_puzzle (p);
70 char ch = getchar ();
71 }
72
73 /* set the password for the puzzle */
74 void do_set_password (Puzzle *p)
75 {
76 char* password;
77 password = getpass (INPUT_PASSWORD);
78 /* if empty reset the password to nothing */
79 if (strlen(password) == 0)
80 {
81 set_puzzle_password (p, "\0");
82 printf (PASSWORD_RESET);
83 char ch = getchar ();
84 }
85 /* set the password */
86 else
87 {
88 set_puzzle_password (p, (const char* )password);
89 printf (PASSWORD_SET);
90 char ch = getchar ();
91 }
92 }
93
94 /* set clue for a word - only for frozen grid */
95 void do_set_clue_word (Puzzle *p, enum ORIENTATION orient)
96 {
97 print_puzzle (p);
98 if (p->grid_frozen == false)
99 {
100 printf (UNFROZEN_GRID);
101 char ch = getchar ();
102 return;
103 }
104 int index;
105 String clue;
106 printf (INPUT_INDEX);
107 index = get_num ();
108 printf (INPUT_CLUE);
109 fgets (clue, MAX_CLUE_LENGTH, stdin);
110 if (strlen (clue) == 1)
111 return;
112 char* cl = strtok (clue, "\n");
113
114 bool res;
115 res = set_clue (p, cl, index, orient);
116
117 if (res == false)
118 {
119 printf (NO_WORD_INDEX);
120 char ch = getchar ();
121 }
122 }
123
124 /* clear a cell in the grid */
125 void do_clear_cell (Puzzle *p)
126 {
127 print_puzzle (p);
128 if (p->grid_frozen == true)
129 {
130 printf (FROZEN_GRID);
131 char ch = getchar ();
132 return;
133 }
134 int row, col;
135 printf (INPUT_ROW);
136 row = get_num ();
137 printf (INPUT_COL);
138 col = get_num ();
139 if (row >= p->grid_size || col >= p->grid_size)
140 {
141 printf (EXCEED_GRID_SIZE);
142 char ch = getchar ();
143 return;
144 }
145 p->chars[row][col] = ' ';
146 print_puzzle (p);
147
148 char ch = getchar ();
149 }
150
151 /* add a down word to the grid */
152 void do_add_down_word (Puzzle *p)
153 {
154 print_puzzle (p);
155 if (p->grid_frozen == true)
156 {
157 printf (FROZEN_GRID);
158 char ch = getchar ();
159 return;
160 }
161 char wd[MAX_PUZZLE_SIZE];
162 int row, col;
163 printf (INPUT_WORD);
164 fgets (wd, MAX_PUZZLE_SIZE, stdin);
165 char *word = is_valid_word (wd);
166 if (word == NULL)
167 {
168 printf (INVALID_WORD);
169 char ch = getchar ();
170 return;
171 }
172 printf (INPUT_ROW);
173 row = get_num ();
174 printf (INPUT_COL);
175 col = get_num ();
176 if (row >= p->grid_size || col >= p->grid_size)
177 {
178 printf (EXCEED_GRID_SIZE);
179 char ch = getchar ();
180 return;
181 }
182 if (strlen (word) > (p->grid_size - row))
183 {
184 printf (WORD_TOO_LONG);
185 char ch = getchar ();
186 return;
187 }
188
189 for (int i = row; i < row + strlen(word); i ++)
190 p->chars[i][col] = toupper(word[i - row]);
191
192 print_puzzle (p);
193 char ch = getchar ();
194 }
195
196 /* add an across word to the grid */
197 void do_add_across_word (Puzzle *p)
198 {
199 print_puzzle (p);
200 if (p->grid_frozen == true)
201 {
202 printf (FROZEN_GRID);
203 char ch = getchar ();
204 return;
205 }
206 char wd[MAX_PUZZLE_SIZE];
207 int row, col;
208 printf (INPUT_WORD);
209 fgets (wd, MAX_PUZZLE_SIZE, stdin);
210 char *word = is_valid_word (wd);
211 if (word == NULL)
212 {
213 printf (INVALID_WORD);
214 char ch = getchar ();
215 return;
216 }
217 printf (INPUT_ROW);
218 row = get_num ();
219 printf (INPUT_COL);
220 col = get_num ();
221 if (row >= p->grid_size || col >= p->grid_size)
222 {
223 printf (EXCEED_GRID_SIZE);
224 char ch = getchar ();
225 return;
226 }
227
228 if (strlen (word) > (p->grid_size - col))
229 {
230 printf (WORD_TOO_LONG);
231 char ch = getchar ();
232 return;
233 }
234
235 for (int i = col; i < col+strlen (word); i ++)
236 p->chars[row][i] = toupper(word[i - col]);
237
238 print_puzzle (p);
239 char ch = getchar ();
240 }
241 /* confirm exit */
242 bool do_confirm_exit ()
243 {
244 printf (INPUT_CONFIRM_EXIT);
245 char res[3];
246 fgets (res, 3, stdin);
247 if (toupper(res[0]) == 'Y')
248 return true;
249 else
250 return false;
251 }
252
253 /* main loop for the puzzle editor */
254 void puzzle_editor_loop (Puzzle *p, const char *filename)
255 {
256 bool loop = true;
257 while (loop)
258 {
259 char puzzle_title[60];
260 sprintf (puzzle_title, "%s - %s", PUZZLE_MENU_TITLE, filename);
261 print_menu (WHITE, BLUE, puzzle_title, PUZZLE_EDIT_MENU, 14, 50);
262 printf (INPUT_CHOICE);
263 int ch = get_num ();
264 switch (ch)
265 {
266 case 1: print_puzzle (p);
267 char ch = getchar ();
268 break;
269 case 2: do_add_across_word (p);
270 break;
271 case 3: do_add_down_word (p);
272 break;
273 case 4: do_clear_cell (p);
274 break;
275 case 5: freeze_puzzle (p);
276 print_puzzle (p);
277 ch = getchar ();
278 break;
279 case 6: unfreeze_puzzle (p);
280 print_puzzle (p);
281 ch = getchar ();
282 break;
283 case 7: do_set_clue_word (p, ACROSS);
284 break;
285 case 8: do_set_clue_word (p, DOWN);
286 break;
287 case 9: save_puzzle (p, filename);
288 printf ("%s\n",FILE_SAVED);
289 ch = getchar ();
290 break;
291 case 10: do_set_password (p);
292 break;
293 case 11: do_reset_puzzle (p);
294 break;
295 case 12: do_export_puzzle (p);
296 break;
297 case 13: do_export_clues (p);
298 break;
299 case 14: loop = ! do_confirm_exit ();
300 break;
301 }
302 }
303 }
304
305 /* open an existing puzzle */
306 void do_open_puzzle (const char *filename)
307 {
308 Puzzle p;
309 /* if no filename is provided, get it from command line */
310 if (filename == NULL)
311 {
312 printf (INPUT_FILE);
313 char fname[256];
314 fgets(fname, 256, stdin);
315 if (strlen (fname) == 1)
316 return;
317 filename = strtok (fname, "\n");
318 }
319
320 p = load_puzzle (filename);
321
322 if (strcmp (p.hashed_password, "\0") != 0)
323 {
324 char *passwd;
325 passwd = getpass (INPUT_PASSWORD);
326 if (strlen (passwd) == 0)
327 return;
328
329 if (verify_password (&p, (const char*) passwd))
330 puzzle_editor_loop (&p, filename);
331 else
332 {
333 printf (WRONG_PASSWORD);
334 char ch = getchar ();
335 }
336 }
337 else
338 puzzle_editor_loop (&p, filename);
339 }
340
341 /* create a new blank puzzle */
342 void do_new_puzzle (char *filename, int size)
343 {
344 Puzzle p;
345 /* if filename is not provided get it from command line */
346 if (filename == NULL)
347 {
348 printf (INPUT_FILE);
349 char fname[256];
350 fgets (fname, 256, stdin);
351 if (strlen (fname) == 1)
352 return;
353 filename = strtok (fname, "\n");
354 }
355 /* if no size is specified get it from command line */
356 if (size == -1)
357 {
358 printf (INPUT_GRID_SIZE);
359 size = get_num ();
360 }
361
362 if (size > MAX_PUZZLE_SIZE)
363 {
364 printf (EXCEED_MAX_GRID_SIZE);
365 char c = getchar ();
366 }
367 else
368 {
369 init_puzzle (&p, size);
370 puzzle_editor_loop (&p, filename);
371 }
372 }
373
374 /* The main loop of the program */
375 int main_loop ()
376 {
377 /* Print the main menu */
378 while (1)
379 {
380 print_menu (WHITE, BLUE, MAIN_MENU_TITLE, MAIN_MENU, 3, 50);
381 printf (INPUT_CHOICE);
382 int ch = get_num ();
383 switch (ch)
384 {
385 case 1: do_new_puzzle (NULL, -1);
386 break;
387 case 2: do_open_puzzle (NULL);
388 break;
389 case 3: exit (0);
390 }
391 }
392 }
393
394 int main (int argc, char* argv[])
395 {
396 if (argc >= 2)
397 {
398 Puzzle p;
399 switch (argc)
400 {
401 case 2 : do_open_puzzle (argv[1]);
402 break;
403 case 4 : if (strcmp (argv[2], "new") == 0)
404 {
405 int grid_size = atoi (argv[3]);
406 do_new_puzzle (argv[1], grid_size);
407 break;
408 }
409 default: fprintf (stderr, USAGE_LINE_1, argv[0]);
410 fprintf (stderr, USAGE_LINE_2);
411 fprintf (stderr, USAGE_LINE_3);
412 exit (3);
413 }
414 }
415 return (main_loop ());
416 }