summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/puzzles.h
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/puzzles.h')
-rw-r--r--apps/plugins/puzzles/src/puzzles.h251
1 files changed, 176 insertions, 75 deletions
diff --git a/apps/plugins/puzzles/src/puzzles.h b/apps/plugins/puzzles/src/puzzles.h
index 29b00ddaf0..44a056d78f 100644
--- a/apps/plugins/puzzles/src/puzzles.h
+++ b/apps/plugins/puzzles/src/puzzles.h
@@ -18,6 +18,9 @@
18#define STR_INT(x) #x 18#define STR_INT(x) #x
19#define STR(x) STR_INT(x) 19#define STR(x) STR_INT(x)
20 20
21/* An upper bound on the length of sprintf'ed integers (signed or unsigned). */
22#define MAX_DIGITS(x) (sizeof(x) * CHAR_BIT / 3 + 2)
23
21/* NB not perfect because they evaluate arguments multiple times. */ 24/* NB not perfect because they evaluate arguments multiple times. */
22#ifndef max 25#ifndef max
23#define max(x,y) ( (x)>(y) ? (x) : (y) ) 26#define max(x,y) ( (x)>(y) ? (x) : (y) )
@@ -69,6 +72,7 @@ enum {
69 (m) == CURSOR_RIGHT || (m) == CURSOR_LEFT ) 72 (m) == CURSOR_RIGHT || (m) == CURSOR_LEFT )
70#define IS_CURSOR_SELECT(m) ( (m) == CURSOR_SELECT || (m) == CURSOR_SELECT2) 73#define IS_CURSOR_SELECT(m) ( (m) == CURSOR_SELECT || (m) == CURSOR_SELECT2)
71#define IS_UI_FAKE_KEY(m) ( (m) > UI_LOWER_BOUND && (m) < UI_UPPER_BOUND ) 74#define IS_UI_FAKE_KEY(m) ( (m) > UI_LOWER_BOUND && (m) < UI_UPPER_BOUND )
75#define STRIP_BUTTON_MODIFIERS(m) ( (unsigned)(m) & ~MOD_MASK )
72 76
73/* 77/*
74 * Flags in the back end's `flags' word. 78 * Flags in the back end's `flags' word.
@@ -83,14 +87,6 @@ enum {
83#define REQUIRE_NUMPAD ( 1 << 11 ) 87#define REQUIRE_NUMPAD ( 1 << 11 )
84/* end of `flags' word definitions */ 88/* end of `flags' word definitions */
85 89
86#ifdef _WIN32_WCE
87 /* Pocket PC devices have small, portrait screen that requires more vivid colours */
88 #define SMALL_SCREEN
89 #define PORTRAIT_SCREEN
90 #define VIVID_COLOURS
91 #define STYLUS_BASED
92#endif
93
94#define IGNOREARG(x) ( (x) = (x) ) 90#define IGNOREARG(x) ( (x) = (x) )
95 91
96typedef struct frontend frontend; 92typedef struct frontend frontend;
@@ -132,8 +128,13 @@ typedef struct psdata psdata;
132 */ 128 */
133enum { C_STRING, C_CHOICES, C_BOOLEAN, C_END }; 129enum { C_STRING, C_CHOICES, C_BOOLEAN, C_END };
134struct config_item { 130struct config_item {
135 /* Not dynamically allocated */ 131 /* Not dynamically allocated: the GUI display name for the option */
136 const char *name; 132 const char *name;
133 /* Not dynamically allocated: the keyword identifier for the
134 * option. Only examined in the case where this structure is being
135 * used for options that appear in config files, i.e. the
136 * get_prefs method fills this in but configure does not. */
137 const char *kw;
137 /* Value from the above C_* enum */ 138 /* Value from the above C_* enum */
138 int type; 139 int type;
139 union { 140 union {
@@ -151,6 +152,13 @@ struct config_item {
151 */ 152 */
152 const char *choicenames; 153 const char *choicenames;
153 /* 154 /*
155 * choicekws is non-NULL, not dynamically allocated, and
156 * contains a parallel list of keyword strings used to
157 * represent the enumeration in config files. As with 'kw'
158 * above, this is only expected to be set by get_prefs.
159 */
160 const char *choicekws;
161 /*
154 * Indicates the chosen index from the options in 162 * Indicates the chosen index from the options in
155 * choicenames. In the above example, 0==Foo, 1==Bar and 163 * choicenames. In the above example, 0==Foo, 1==Bar and
156 * 2==Baz. 164 * 2==Baz.
@@ -256,8 +264,10 @@ void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize,
256 int align, int colour, const char *text); 264 int align, int colour, const char *text);
257void draw_rect(drawing *dr, int x, int y, int w, int h, int colour); 265void draw_rect(drawing *dr, int x, int y, int w, int h, int colour);
258void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour); 266void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour);
259void draw_polygon(drawing *dr, int *coords, int npoints, 267void draw_polygon(drawing *dr, const int *coords, int npoints,
260 int fillcolour, int outlinecolour); 268 int fillcolour, int outlinecolour);
269void draw_polygon_fallback(drawing *dr, const int *coords, int npoints,
270 int fillcolour, int outlinecolour);
261void draw_circle(drawing *dr, int cx, int cy, int radius, 271void draw_circle(drawing *dr, int cx, int cy, int radius,
262 int fillcolour, int outlinecolour); 272 int fillcolour, int outlinecolour);
263void draw_thick_line(drawing *dr, float thickness, 273void draw_thick_line(drawing *dr, float thickness,
@@ -307,13 +317,16 @@ void midend_free(midend *me);
307const game *midend_which_game(midend *me); 317const game *midend_which_game(midend *me);
308void midend_set_params(midend *me, game_params *params); 318void midend_set_params(midend *me, game_params *params);
309game_params *midend_get_params(midend *me); 319game_params *midend_get_params(midend *me);
310void midend_size(midend *me, int *x, int *y, bool user_size); 320void midend_size(midend *me, int *x, int *y, bool user_size,
321 double device_pixel_ratio);
311void midend_reset_tilesize(midend *me); 322void midend_reset_tilesize(midend *me);
312void midend_new_game(midend *me); 323void midend_new_game(midend *me);
313void midend_restart_game(midend *me); 324void midend_restart_game(midend *me);
314void midend_stop_anim(midend *me); 325void midend_stop_anim(midend *me);
315bool midend_process_key(midend *me, int x, int y, int button); 326enum { PKR_QUIT = 0, PKR_SOME_EFFECT, PKR_NO_EFFECT, PKR_UNUSED };
327int midend_process_key(midend *me, int x, int y, int button);
316key_label *midend_request_keys(midend *me, int *nkeys); 328key_label *midend_request_keys(midend *me, int *nkeys);
329const char *midend_current_key_label(midend *me, int button);
317void midend_force_redraw(midend *me); 330void midend_force_redraw(midend *me);
318void midend_redraw(midend *me); 331void midend_redraw(midend *me);
319float *midend_colours(midend *me, int *ncolours); 332float *midend_colours(midend *me, int *ncolours);
@@ -322,7 +335,7 @@ void midend_timer(midend *me, float tplus);
322struct preset_menu *midend_get_presets(midend *me, int *id_limit); 335struct preset_menu *midend_get_presets(midend *me, int *id_limit);
323int midend_which_preset(midend *me); 336int midend_which_preset(midend *me);
324bool midend_wants_statusbar(midend *me); 337bool midend_wants_statusbar(midend *me);
325enum { CFG_SETTINGS, CFG_SEED, CFG_DESC, CFG_FRONTEND_SPECIFIC }; 338enum { CFG_SETTINGS, CFG_SEED, CFG_DESC, CFG_PREFS, CFG_FRONTEND_SPECIFIC };
326config_item *midend_get_config(midend *me, int which, char **wintitle); 339config_item *midend_get_config(midend *me, int which, char **wintitle);
327const char *midend_set_config(midend *me, int which, config_item *cfg); 340const char *midend_set_config(midend *me, int which, config_item *cfg);
328const char *midend_game_id(midend *me, const char *id); 341const char *midend_game_id(midend *me, const char *id);
@@ -343,6 +356,11 @@ void midend_serialise(midend *me,
343const char *midend_deserialise(midend *me, 356const char *midend_deserialise(midend *me,
344 bool (*read)(void *ctx, void *buf, int len), 357 bool (*read)(void *ctx, void *buf, int len),
345 void *rctx); 358 void *rctx);
359const char *midend_load_prefs(
360 midend *me, bool (*read)(void *ctx, void *buf, int len), void *rctx);
361void midend_save_prefs(midend *me,
362 void (*write)(void *ctx, const void *buf, int len),
363 void *wctx);
346const char *identify_game(char **name, 364const char *identify_game(char **name,
347 bool (*read)(void *ctx, void *buf, int len), 365 bool (*read)(void *ctx, void *buf, int len),
348 void *rctx); 366 void *rctx);
@@ -374,12 +392,22 @@ void free_cfg(config_item *cfg);
374void free_keys(key_label *keys, int nkeys); 392void free_keys(key_label *keys, int nkeys);
375void obfuscate_bitmap(unsigned char *bmp, int bits, bool decode); 393void obfuscate_bitmap(unsigned char *bmp, int bits, bool decode);
376char *fgetline(FILE *fp); 394char *fgetline(FILE *fp);
395char *make_prefs_path(const char *dir, const char *sep,
396 const game *game, const char *suffix);
397int n_times_root_k(int n, int k);
377 398
378/* allocates output each time. len is always in bytes of binary data. 399/* allocates output each time. len is always in bytes of binary data.
379 * May assert (or just go wrong) if lengths are unchecked. */ 400 * May assert (or just go wrong) if lengths are unchecked. */
380char *bin2hex(const unsigned char *in, int inlen); 401char *bin2hex(const unsigned char *in, int inlen);
381unsigned char *hex2bin(const char *in, int outlen); 402unsigned char *hex2bin(const char *in, int outlen);
382 403
404/* Returns 0 or 1 if the environment variable is set, or dflt if not.
405 * dflt may be a third value if it needs to be. */
406int getenv_bool(const char *name, int dflt);
407
408/* Mixes two colours in specified proportions. */
409void colour_mix(const float src1[3], const float src2[3], float p,
410 float dst[3]);
383/* Sets (and possibly dims) background from frontend default colour, 411/* Sets (and possibly dims) background from frontend default colour,
384 * and auto-generates highlight and lowlight colours too. */ 412 * and auto-generates highlight and lowlight colours too. */
385void game_mkhighlight(frontend *fe, float *ret, 413void game_mkhighlight(frontend *fe, float *ret,
@@ -392,14 +420,15 @@ void game_mkhighlight_specific(frontend *fe, float *ret,
392/* Randomly shuffles an array of items. */ 420/* Randomly shuffles an array of items. */
393void shuffle(void *array, int nelts, int eltsize, random_state *rs); 421void shuffle(void *array, int nelts, int eltsize, random_state *rs);
394 422
395/* Draw a rectangle outline, using the drawing API's draw_line. */ 423/* Draw a rectangle outline, using the drawing API's draw_polygon. */
396void draw_rect_outline(drawing *dr, int x, int y, int w, int h, 424void draw_rect_outline(drawing *dr, int x, int y, int w, int h,
397 int colour); 425 int colour);
398 426
399/* Draw a set of rectangle corners (e.g. for a cursor display). */ 427/* Draw a set of rectangle corners (e.g. for a cursor display). */
400void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col); 428void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col);
401 429
402void move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap); 430char *move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap,
431 bool *visible);
403 432
404/* Used in netslide.c and sixteen.c for cursor movement around edge. */ 433/* Used in netslide.c and sixteen.c for cursor movement around edge. */
405int c2pos(int w, int h, int cx, int cy); 434int c2pos(int w, int h, int cx, int cy);
@@ -416,37 +445,55 @@ void draw_text_outline(drawing *dr, int x, int y, int fonttype,
416 * less than buffer size. */ 445 * less than buffer size. */
417void copy_left_justified(char *buf, size_t sz, const char *str); 446void copy_left_justified(char *buf, size_t sz, const char *str);
418 447
419/* An ugly, but working float-to-string implementation for platforms
420 * that don't have one */
421int ftoa(char *buf, float f);
422
423/* Returns a generic label based on the value of `button.' To be used 448/* Returns a generic label based on the value of `button.' To be used
424 whenever a `label' field returned by the request_keys() game 449 whenever a `label' field returned by the request_keys() game
425 function is NULL. Dynamically allocated, to be freed by caller. */ 450 function is NULL. Dynamically allocated, to be freed by caller. */
426char *button2label(int button); 451char *button2label(int button);
427 452
453/* Swap two regions of memory. The two regions must not
454 * overlap. (Note: the natural name for this might be "memswap", but
455 * the mem* namespace is reserved for future expansion by the C99
456 * standard per clause 7.26.11.1.) */
457void swap_regions(void *av, void *bv, size_t size);
458
459/* comparator for sorting ints with qsort() */
460int compare_integers(const void *av, const void *bv);
461
428/* 462/*
429 * dsf.c 463 * dsf.c
430 */ 464 */
431int *snew_dsf(int size); 465typedef struct DSF DSF;
432 466DSF *dsf_new(int size);
433void print_dsf(int *dsf, int size); 467void dsf_free(DSF *dsf);
434 468
435/* Return the canonical element of the equivalence class containing element 469void dsf_copy(DSF *to, DSF *from);
436 * val. If 'inverse' is non-NULL, this function will put into it a flag 470
437 * indicating whether the canonical element is inverse to val. */ 471/* Basic dsf operations, return the canonical element of a class,
438int edsf_canonify(int *dsf, int val, bool *inverse); 472 * check if two elements are in the same class, and return the size of
439int dsf_canonify(int *dsf, int val); 473 * a class. These work on all types of dsf. */
440int dsf_size(int *dsf, int val); 474int dsf_canonify(DSF *dsf, int n);
441 475bool dsf_equivalent(DSF *dsf, int n1, int n2);
442/* Allow the caller to specify that two elements should be in the same 476int dsf_size(DSF *dsf, int n);
443 * equivalence class. If 'inverse' is true, the elements are actually opposite 477
444 * to one another in some sense. This function will fail an assertion if the 478/* Merge two elements and their classes. Not legal on a flip dsf. */
445 * caller gives it self-contradictory data, ie if two elements are claimed to 479void dsf_merge(DSF *dsf, int n1, int n2);
446 * be both opposite and non-opposite. */ 480
447void edsf_merge(int *dsf, int v1, int v2, bool inverse); 481/* Special dsf that tracks the minimal element of every equivalence
448void dsf_merge(int *dsf, int v1, int v2); 482 * class, and a function to query it. */
449void dsf_init(int *dsf, int len); 483DSF *dsf_new_min(int size);
484int dsf_minimal(DSF *dsf, int n);
485
486/* Special dsf that tracks whether pairs of elements in the same class
487 * have flipped sense relative to each other. Merge function takes an
488 * argument saying whether n1 and n2 are opposite to each other;
489 * canonify function will report whether n is opposite to the returned
490 * element. */
491DSF *dsf_new_flip(int size);
492void dsf_merge_flip(DSF *dsf, int n1, int n2, bool flip);
493int dsf_canonify_flip(DSF *dsf, int n, bool *flip);
494
495/* Reinitialise a dsf to the starting 'all elements distinct' state. */
496void dsf_reinit(DSF *dsf);
450 497
451/* 498/*
452 * tdq.c 499 * tdq.c
@@ -507,7 +554,7 @@ void random_free(random_state *state);
507char *random_state_encode(random_state *state); 554char *random_state_encode(random_state *state);
508random_state *random_state_decode(const char *input); 555random_state *random_state_decode(const char *input);
509/* random.c also exports SHA, which occasionally comes in useful. */ 556/* random.c also exports SHA, which occasionally comes in useful. */
510#if __STDC_VERSION__ >= 199901L 557#if HAVE_STDINT_H
511#include <stdint.h> 558#include <stdint.h>
512typedef uint32_t uint32; 559typedef uint32_t uint32;
513#elif UINT_MAX >= 4294967295L 560#elif UINT_MAX >= 4294967295L
@@ -532,7 +579,7 @@ void SHA_Simple(const void *p, int len, unsigned char *output);
532document *document_new(int pw, int ph, float userscale); 579document *document_new(int pw, int ph, float userscale);
533void document_free(document *doc); 580void document_free(document *doc);
534void document_add_puzzle(document *doc, const game *game, game_params *par, 581void document_add_puzzle(document *doc, const game *game, game_params *par,
535 game_state *st, game_state *st2); 582 game_ui *ui, game_state *st, game_state *st2);
536int document_npages(const document *doc); 583int document_npages(const document *doc);
537void document_begin(const document *doc, drawing *dr); 584void document_begin(const document *doc, drawing *dr);
538void document_end(const document *doc, drawing *dr); 585void document_end(const document *doc, drawing *dr);
@@ -564,7 +611,9 @@ void free_combi(combi_ctx *combi);
564 * divvy.c 611 * divvy.c
565 */ 612 */
566/* divides w*h rectangle into pieces of size k. Returns w*h dsf. */ 613/* divides w*h rectangle into pieces of size k. Returns w*h dsf. */
567int *divvy_rectangle(int w, int h, int k, random_state *rs); 614DSF *divvy_rectangle(int w, int h, int k, random_state *rs);
615/* Same, but only tries once, and may fail. (Exposed for test program.) */
616DSF *divvy_rectangle_attempt(int w, int h, int k, random_state *rs);
568 617
569/* 618/*
570 * findloop.c 619 * findloop.c
@@ -661,19 +710,24 @@ struct game {
661 bool can_format_as_text_ever; 710 bool can_format_as_text_ever;
662 bool (*can_format_as_text_now)(const game_params *params); 711 bool (*can_format_as_text_now)(const game_params *params);
663 char *(*text_format)(const game_state *state); 712 char *(*text_format)(const game_state *state);
713 config_item *(*get_prefs)(game_ui *ui);
714 void (*set_prefs)(game_ui *ui, const config_item *cfg);
664 game_ui *(*new_ui)(const game_state *state); 715 game_ui *(*new_ui)(const game_state *state);
665 void (*free_ui)(game_ui *ui); 716 void (*free_ui)(game_ui *ui);
666 char *(*encode_ui)(const game_ui *ui); 717 char *(*encode_ui)(const game_ui *ui);
667 void (*decode_ui)(game_ui *ui, const char *encoding); 718 void (*decode_ui)(game_ui *ui, const char *encoding,
719 const game_state *state);
668 key_label *(*request_keys)(const game_params *params, int *nkeys); 720 key_label *(*request_keys)(const game_params *params, int *nkeys);
669 void (*changed_state)(game_ui *ui, const game_state *oldstate, 721 void (*changed_state)(game_ui *ui, const game_state *oldstate,
670 const game_state *newstate); 722 const game_state *newstate);
723 const char *(*current_key_label)(const game_ui *ui,
724 const game_state *state, int button);
671 char *(*interpret_move)(const game_state *state, game_ui *ui, 725 char *(*interpret_move)(const game_state *state, game_ui *ui,
672 const game_drawstate *ds, int x, int y, int button); 726 const game_drawstate *ds, int x, int y, int button);
673 game_state *(*execute_move)(const game_state *state, const char *move); 727 game_state *(*execute_move)(const game_state *state, const char *move);
674 int preferred_tilesize; 728 int preferred_tilesize;
675 void (*compute_size)(const game_params *params, int tilesize, 729 void (*compute_size)(const game_params *params, int tilesize,
676 int *x, int *y); 730 const game_ui *ui, int *x, int *y);
677 void (*set_size)(drawing *dr, game_drawstate *ds, 731 void (*set_size)(drawing *dr, game_drawstate *ds,
678 const game_params *params, int tilesize); 732 const game_params *params, int tilesize);
679 float *(*colours)(frontend *fe, int *ncolours); 733 float *(*colours)(frontend *fe, int *ncolours);
@@ -693,51 +747,86 @@ struct game {
693 int *x, int *y, int *w, int *h); 747 int *x, int *y, int *w, int *h);
694 int (*status)(const game_state *state); 748 int (*status)(const game_state *state);
695 bool can_print, can_print_in_colour; 749 bool can_print, can_print_in_colour;
696 void (*print_size)(const game_params *params, float *x, float *y); 750 void (*print_size)(const game_params *params, const game_ui *ui,
697 void (*print)(drawing *dr, const game_state *state, int tilesize); 751 float *x, float *y);
752 void (*print)(drawing *dr, const game_state *state, const game_ui *ui,
753 int tilesize);
698 bool wants_statusbar; 754 bool wants_statusbar;
699 bool is_timed; 755 bool is_timed;
700 bool (*timing_state)(const game_state *state, game_ui *ui); 756 bool (*timing_state)(const game_state *state, game_ui *ui);
701 int flags; 757 int flags;
702}; 758};
703 759
760#define GET_HANDLE_AS_TYPE(dr, type) ((type*)((dr)->handle))
761
762struct drawing {
763 const drawing_api *api;
764 void *handle;
765};
766
704/* 767/*
705 * Data structure containing the drawing API implemented by the 768 * Data structure containing the drawing API implemented by the
706 * front end and also by cross-platform printing modules such as 769 * front end and also by cross-platform printing modules such as
707 * PostScript. 770 * PostScript.
708 */ 771 */
709struct drawing_api { 772struct drawing_api {
710 void (*draw_text)(void *handle, int x, int y, int fonttype, int fontsize, 773 /*
774 * API version. Increment this when there is a breaking change to
775 * this API which requires front ends to change.
776 *
777 * There is expliclty not a public LATEST_API_VERSION define, so
778 * that front end authors will need to manually intervene when the
779 * version number changes. Naturally, this should be done
780 * sparingly.
781 *
782 * If a function is ever added to this API, please move this field
783 * to the _end_ of the structure, so that changes thereafter will
784 * shift the position of the version and lead to a compilation
785 * error if old implementations are not updated. Then remove this
786 * comment.
787 *
788 * The latest version number is 1.
789 *
790 * Change log:
791 *
792 * Version 1 (2024-08-14): Introduction of version number, in
793 * conjunction with changing every API function to take `drawing
794 * *` instead of `void *`. See commit f379130 for the detailed
795 * rationale behind this change.
796 */
797 int version;
798
799 void (*draw_text)(drawing *dr, int x, int y, int fonttype, int fontsize,
711 int align, int colour, const char *text); 800 int align, int colour, const char *text);
712 void (*draw_rect)(void *handle, int x, int y, int w, int h, int colour); 801 void (*draw_rect)(drawing *dr, int x, int y, int w, int h, int colour);
713 void (*draw_line)(void *handle, int x1, int y1, int x2, int y2, 802 void (*draw_line)(drawing *dr, int x1, int y1, int x2, int y2,
714 int colour); 803 int colour);
715 void (*draw_polygon)(void *handle, int *coords, int npoints, 804 void (*draw_polygon)(drawing *dr, const int *coords, int npoints,
716 int fillcolour, int outlinecolour); 805 int fillcolour, int outlinecolour);
717 void (*draw_circle)(void *handle, int cx, int cy, int radius, 806 void (*draw_circle)(drawing *dr, int cx, int cy, int radius,
718 int fillcolour, int outlinecolour); 807 int fillcolour, int outlinecolour);
719 void (*draw_update)(void *handle, int x, int y, int w, int h); 808 void (*draw_update)(drawing *dr, int x, int y, int w, int h);
720 void (*clip)(void *handle, int x, int y, int w, int h); 809 void (*clip)(drawing *dr, int x, int y, int w, int h);
721 void (*unclip)(void *handle); 810 void (*unclip)(drawing *dr);
722 void (*start_draw)(void *handle); 811 void (*start_draw)(drawing *dr);
723 void (*end_draw)(void *handle); 812 void (*end_draw)(drawing *dr);
724 void (*status_bar)(void *handle, const char *text); 813 void (*status_bar)(drawing *dr, const char *text);
725 blitter *(*blitter_new)(void *handle, int w, int h); 814 blitter *(*blitter_new)(drawing *dr, int w, int h);
726 void (*blitter_free)(void *handle, blitter *bl); 815 void (*blitter_free)(drawing *dr, blitter *bl);
727 void (*blitter_save)(void *handle, blitter *bl, int x, int y); 816 void (*blitter_save)(drawing *dr, blitter *bl, int x, int y);
728 void (*blitter_load)(void *handle, blitter *bl, int x, int y); 817 void (*blitter_load)(drawing *dr, blitter *bl, int x, int y);
729 void (*begin_doc)(void *handle, int pages); 818 void (*begin_doc)(drawing *dr, int pages);
730 void (*begin_page)(void *handle, int number); 819 void (*begin_page)(drawing *dr, int number);
731 void (*begin_puzzle)(void *handle, float xm, float xc, 820 void (*begin_puzzle)(drawing *dr, float xm, float xc,
732 float ym, float yc, int pw, int ph, float wmm); 821 float ym, float yc, int pw, int ph, float wmm);
733 void (*end_puzzle)(void *handle); 822 void (*end_puzzle)(drawing *dr);
734 void (*end_page)(void *handle, int number); 823 void (*end_page)(drawing *dr, int number);
735 void (*end_doc)(void *handle); 824 void (*end_doc)(drawing *dr);
736 void (*line_width)(void *handle, float width); 825 void (*line_width)(drawing *dr, float width);
737 void (*line_dotted)(void *handle, bool dotted); 826 void (*line_dotted)(drawing *dr, bool dotted);
738 char *(*text_fallback)(void *handle, const char *const *strings, 827 char *(*text_fallback)(drawing *dr, const char *const *strings,
739 int nstrings); 828 int nstrings);
740 void (*draw_thick_line)(void *handle, float thickness, 829 void (*draw_thick_line)(drawing *dr, float thickness,
741 float x1, float y1, float x2, float y2, 830 float x1, float y1, float x2, float y2,
742 int colour); 831 int colour);
743}; 832};
@@ -750,17 +839,29 @@ struct drawing_api {
750#ifdef COMBINED 839#ifdef COMBINED
751extern const game *gamelist[]; 840extern const game *gamelist[];
752extern const int gamecount; 841extern const int gamecount;
842/* Also pre-declare every individual 'struct game' we expect */
843#define GAME(x) extern const game x;
844#include "generated-games.h"
845#undef GAME
753#else 846#else
754extern const game thegame; 847extern const game thegame;
755#endif 848#endif
756 849
757/* 850/*
758 * Special string value to return from interpret_move in the case 851 * Special string values to return from interpret_move.
759 * where the game UI has been updated but no actual move is being 852 *
760 * appended to the undo chain. Must be declared as a non-const char, 853 * MOVE_UI_UPDATE is for the case where the game UI has been updated
761 * but should never actually be modified by anyone. 854 * but no actual move is being appended to the undo chain.
855 *
856 * MOVE_NO_EFFECT is for when the key was understood by the puzzle,
857 * but it happens that there isn't effect, not even a UI change.
858 *
859 * MOVE_UNUSED is for keys that the puzzle has no use for at all.
860 *
861 * Each must be declared as a non-const char, but should never
862 * actually be modified by anyone.
762 */ 863 */
763extern char UI_UPDATE[]; 864extern char MOVE_UI_UPDATE[], MOVE_NO_EFFECT[], MOVE_UNUSED[];
764 865
765/* A little bit of help to lazy developers */ 866/* A little bit of help to lazy developers */
766#define DEFAULT_STATUSBAR_TEXT "Use status_bar() to fill this in." 867#define DEFAULT_STATUSBAR_TEXT "Use status_bar() to fill this in."