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.h165
1 files changed, 114 insertions, 51 deletions
diff --git a/apps/plugins/puzzles/src/puzzles.h b/apps/plugins/puzzles/src/puzzles.h
index 29b00ddaf0..2c52bc6cde 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,7 +264,7 @@ 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);
261void draw_circle(drawing *dr, int cx, int cy, int radius, 269void draw_circle(drawing *dr, int cx, int cy, int radius,
262 int fillcolour, int outlinecolour); 270 int fillcolour, int outlinecolour);
@@ -307,13 +315,16 @@ void midend_free(midend *me);
307const game *midend_which_game(midend *me); 315const game *midend_which_game(midend *me);
308void midend_set_params(midend *me, game_params *params); 316void midend_set_params(midend *me, game_params *params);
309game_params *midend_get_params(midend *me); 317game_params *midend_get_params(midend *me);
310void midend_size(midend *me, int *x, int *y, bool user_size); 318void midend_size(midend *me, int *x, int *y, bool user_size,
319 double device_pixel_ratio);
311void midend_reset_tilesize(midend *me); 320void midend_reset_tilesize(midend *me);
312void midend_new_game(midend *me); 321void midend_new_game(midend *me);
313void midend_restart_game(midend *me); 322void midend_restart_game(midend *me);
314void midend_stop_anim(midend *me); 323void midend_stop_anim(midend *me);
315bool midend_process_key(midend *me, int x, int y, int button); 324enum { PKR_QUIT = 0, PKR_SOME_EFFECT, PKR_NO_EFFECT, PKR_UNUSED };
325int midend_process_key(midend *me, int x, int y, int button);
316key_label *midend_request_keys(midend *me, int *nkeys); 326key_label *midend_request_keys(midend *me, int *nkeys);
327const char *midend_current_key_label(midend *me, int button);
317void midend_force_redraw(midend *me); 328void midend_force_redraw(midend *me);
318void midend_redraw(midend *me); 329void midend_redraw(midend *me);
319float *midend_colours(midend *me, int *ncolours); 330float *midend_colours(midend *me, int *ncolours);
@@ -322,7 +333,7 @@ void midend_timer(midend *me, float tplus);
322struct preset_menu *midend_get_presets(midend *me, int *id_limit); 333struct preset_menu *midend_get_presets(midend *me, int *id_limit);
323int midend_which_preset(midend *me); 334int midend_which_preset(midend *me);
324bool midend_wants_statusbar(midend *me); 335bool midend_wants_statusbar(midend *me);
325enum { CFG_SETTINGS, CFG_SEED, CFG_DESC, CFG_FRONTEND_SPECIFIC }; 336enum { CFG_SETTINGS, CFG_SEED, CFG_DESC, CFG_PREFS, CFG_FRONTEND_SPECIFIC };
326config_item *midend_get_config(midend *me, int which, char **wintitle); 337config_item *midend_get_config(midend *me, int which, char **wintitle);
327const char *midend_set_config(midend *me, int which, config_item *cfg); 338const char *midend_set_config(midend *me, int which, config_item *cfg);
328const char *midend_game_id(midend *me, const char *id); 339const char *midend_game_id(midend *me, const char *id);
@@ -343,6 +354,11 @@ void midend_serialise(midend *me,
343const char *midend_deserialise(midend *me, 354const char *midend_deserialise(midend *me,
344 bool (*read)(void *ctx, void *buf, int len), 355 bool (*read)(void *ctx, void *buf, int len),
345 void *rctx); 356 void *rctx);
357const char *midend_load_prefs(
358 midend *me, bool (*read)(void *ctx, void *buf, int len), void *rctx);
359void midend_save_prefs(midend *me,
360 void (*write)(void *ctx, const void *buf, int len),
361 void *wctx);
346const char *identify_game(char **name, 362const char *identify_game(char **name,
347 bool (*read)(void *ctx, void *buf, int len), 363 bool (*read)(void *ctx, void *buf, int len),
348 void *rctx); 364 void *rctx);
@@ -374,12 +390,22 @@ void free_cfg(config_item *cfg);
374void free_keys(key_label *keys, int nkeys); 390void free_keys(key_label *keys, int nkeys);
375void obfuscate_bitmap(unsigned char *bmp, int bits, bool decode); 391void obfuscate_bitmap(unsigned char *bmp, int bits, bool decode);
376char *fgetline(FILE *fp); 392char *fgetline(FILE *fp);
393char *make_prefs_path(const char *dir, const char *sep,
394 const game *game, const char *suffix);
395int n_times_root_k(int n, int k);
377 396
378/* allocates output each time. len is always in bytes of binary data. 397/* allocates output each time. len is always in bytes of binary data.
379 * May assert (or just go wrong) if lengths are unchecked. */ 398 * May assert (or just go wrong) if lengths are unchecked. */
380char *bin2hex(const unsigned char *in, int inlen); 399char *bin2hex(const unsigned char *in, int inlen);
381unsigned char *hex2bin(const char *in, int outlen); 400unsigned char *hex2bin(const char *in, int outlen);
382 401
402/* Returns 0 or 1 if the environment variable is set, or dflt if not.
403 * dflt may be a third value if it needs to be. */
404int getenv_bool(const char *name, int dflt);
405
406/* Mixes two colours in specified proportions. */
407void colour_mix(const float src1[3], const float src2[3], float p,
408 float dst[3]);
383/* Sets (and possibly dims) background from frontend default colour, 409/* Sets (and possibly dims) background from frontend default colour,
384 * and auto-generates highlight and lowlight colours too. */ 410 * and auto-generates highlight and lowlight colours too. */
385void game_mkhighlight(frontend *fe, float *ret, 411void game_mkhighlight(frontend *fe, float *ret,
@@ -392,14 +418,15 @@ void game_mkhighlight_specific(frontend *fe, float *ret,
392/* Randomly shuffles an array of items. */ 418/* Randomly shuffles an array of items. */
393void shuffle(void *array, int nelts, int eltsize, random_state *rs); 419void shuffle(void *array, int nelts, int eltsize, random_state *rs);
394 420
395/* Draw a rectangle outline, using the drawing API's draw_line. */ 421/* 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, 422void draw_rect_outline(drawing *dr, int x, int y, int w, int h,
397 int colour); 423 int colour);
398 424
399/* Draw a set of rectangle corners (e.g. for a cursor display). */ 425/* 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); 426void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col);
401 427
402void move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap); 428char *move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap,
429 bool *visible);
403 430
404/* Used in netslide.c and sixteen.c for cursor movement around edge. */ 431/* Used in netslide.c and sixteen.c for cursor movement around edge. */
405int c2pos(int w, int h, int cx, int cy); 432int c2pos(int w, int h, int cx, int cy);
@@ -416,37 +443,52 @@ void draw_text_outline(drawing *dr, int x, int y, int fonttype,
416 * less than buffer size. */ 443 * less than buffer size. */
417void copy_left_justified(char *buf, size_t sz, const char *str); 444void copy_left_justified(char *buf, size_t sz, const char *str);
418 445
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 446/* Returns a generic label based on the value of `button.' To be used
424 whenever a `label' field returned by the request_keys() game 447 whenever a `label' field returned by the request_keys() game
425 function is NULL. Dynamically allocated, to be freed by caller. */ 448 function is NULL. Dynamically allocated, to be freed by caller. */
426char *button2label(int button); 449char *button2label(int button);
427 450
451/* Swap two regions of memory. The two regions must not
452 * overlap. (Note: the natural name for this might be "memswap", but
453 * the mem* namespace is reserved for future expansion by the C99
454 * standard per clause 7.26.11.1.) */
455void swap_regions(void *av, void *bv, size_t size);
456
428/* 457/*
429 * dsf.c 458 * dsf.c
430 */ 459 */
431int *snew_dsf(int size); 460typedef struct DSF DSF;
432 461DSF *dsf_new(int size);
433void print_dsf(int *dsf, int size); 462void dsf_free(DSF *dsf);
434 463
435/* Return the canonical element of the equivalence class containing element 464void dsf_copy(DSF *to, DSF *from);
436 * val. If 'inverse' is non-NULL, this function will put into it a flag 465
437 * indicating whether the canonical element is inverse to val. */ 466/* Basic dsf operations, return the canonical element of a class,
438int edsf_canonify(int *dsf, int val, bool *inverse); 467 * check if two elements are in the same class, and return the size of
439int dsf_canonify(int *dsf, int val); 468 * a class. These work on all types of dsf. */
440int dsf_size(int *dsf, int val); 469int dsf_canonify(DSF *dsf, int n);
441 470bool dsf_equivalent(DSF *dsf, int n1, int n2);
442/* Allow the caller to specify that two elements should be in the same 471int dsf_size(DSF *dsf, int n);
443 * equivalence class. If 'inverse' is true, the elements are actually opposite 472
444 * to one another in some sense. This function will fail an assertion if the 473/* 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 474void dsf_merge(DSF *dsf, int n1, int n2);
446 * be both opposite and non-opposite. */ 475
447void edsf_merge(int *dsf, int v1, int v2, bool inverse); 476/* Special dsf that tracks the minimal element of every equivalence
448void dsf_merge(int *dsf, int v1, int v2); 477 * class, and a function to query it. */
449void dsf_init(int *dsf, int len); 478DSF *dsf_new_min(int size);
479int dsf_minimal(DSF *dsf, int n);
480
481/* Special dsf that tracks whether pairs of elements in the same class
482 * have flipped sense relative to each other. Merge function takes an
483 * argument saying whether n1 and n2 are opposite to each other;
484 * canonify function will report whether n is opposite to the returned
485 * element. */
486DSF *dsf_new_flip(int size);
487void dsf_merge_flip(DSF *dsf, int n1, int n2, bool flip);
488int dsf_canonify_flip(DSF *dsf, int n, bool *flip);
489
490/* Reinitialise a dsf to the starting 'all elements distinct' state. */
491void dsf_reinit(DSF *dsf);
450 492
451/* 493/*
452 * tdq.c 494 * tdq.c
@@ -507,7 +549,7 @@ void random_free(random_state *state);
507char *random_state_encode(random_state *state); 549char *random_state_encode(random_state *state);
508random_state *random_state_decode(const char *input); 550random_state *random_state_decode(const char *input);
509/* random.c also exports SHA, which occasionally comes in useful. */ 551/* random.c also exports SHA, which occasionally comes in useful. */
510#if __STDC_VERSION__ >= 199901L 552#if HAVE_STDINT_H
511#include <stdint.h> 553#include <stdint.h>
512typedef uint32_t uint32; 554typedef uint32_t uint32;
513#elif UINT_MAX >= 4294967295L 555#elif UINT_MAX >= 4294967295L
@@ -532,7 +574,7 @@ void SHA_Simple(const void *p, int len, unsigned char *output);
532document *document_new(int pw, int ph, float userscale); 574document *document_new(int pw, int ph, float userscale);
533void document_free(document *doc); 575void document_free(document *doc);
534void document_add_puzzle(document *doc, const game *game, game_params *par, 576void document_add_puzzle(document *doc, const game *game, game_params *par,
535 game_state *st, game_state *st2); 577 game_ui *ui, game_state *st, game_state *st2);
536int document_npages(const document *doc); 578int document_npages(const document *doc);
537void document_begin(const document *doc, drawing *dr); 579void document_begin(const document *doc, drawing *dr);
538void document_end(const document *doc, drawing *dr); 580void document_end(const document *doc, drawing *dr);
@@ -564,7 +606,9 @@ void free_combi(combi_ctx *combi);
564 * divvy.c 606 * divvy.c
565 */ 607 */
566/* divides w*h rectangle into pieces of size k. Returns w*h dsf. */ 608/* 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); 609DSF *divvy_rectangle(int w, int h, int k, random_state *rs);
610/* Same, but only tries once, and may fail. (Exposed for test program.) */
611DSF *divvy_rectangle_attempt(int w, int h, int k, random_state *rs);
568 612
569/* 613/*
570 * findloop.c 614 * findloop.c
@@ -661,19 +705,24 @@ struct game {
661 bool can_format_as_text_ever; 705 bool can_format_as_text_ever;
662 bool (*can_format_as_text_now)(const game_params *params); 706 bool (*can_format_as_text_now)(const game_params *params);
663 char *(*text_format)(const game_state *state); 707 char *(*text_format)(const game_state *state);
708 config_item *(*get_prefs)(game_ui *ui);
709 void (*set_prefs)(game_ui *ui, const config_item *cfg);
664 game_ui *(*new_ui)(const game_state *state); 710 game_ui *(*new_ui)(const game_state *state);
665 void (*free_ui)(game_ui *ui); 711 void (*free_ui)(game_ui *ui);
666 char *(*encode_ui)(const game_ui *ui); 712 char *(*encode_ui)(const game_ui *ui);
667 void (*decode_ui)(game_ui *ui, const char *encoding); 713 void (*decode_ui)(game_ui *ui, const char *encoding,
714 const game_state *state);
668 key_label *(*request_keys)(const game_params *params, int *nkeys); 715 key_label *(*request_keys)(const game_params *params, int *nkeys);
669 void (*changed_state)(game_ui *ui, const game_state *oldstate, 716 void (*changed_state)(game_ui *ui, const game_state *oldstate,
670 const game_state *newstate); 717 const game_state *newstate);
718 const char *(*current_key_label)(const game_ui *ui,
719 const game_state *state, int button);
671 char *(*interpret_move)(const game_state *state, game_ui *ui, 720 char *(*interpret_move)(const game_state *state, game_ui *ui,
672 const game_drawstate *ds, int x, int y, int button); 721 const game_drawstate *ds, int x, int y, int button);
673 game_state *(*execute_move)(const game_state *state, const char *move); 722 game_state *(*execute_move)(const game_state *state, const char *move);
674 int preferred_tilesize; 723 int preferred_tilesize;
675 void (*compute_size)(const game_params *params, int tilesize, 724 void (*compute_size)(const game_params *params, int tilesize,
676 int *x, int *y); 725 const game_ui *ui, int *x, int *y);
677 void (*set_size)(drawing *dr, game_drawstate *ds, 726 void (*set_size)(drawing *dr, game_drawstate *ds,
678 const game_params *params, int tilesize); 727 const game_params *params, int tilesize);
679 float *(*colours)(frontend *fe, int *ncolours); 728 float *(*colours)(frontend *fe, int *ncolours);
@@ -693,8 +742,10 @@ struct game {
693 int *x, int *y, int *w, int *h); 742 int *x, int *y, int *w, int *h);
694 int (*status)(const game_state *state); 743 int (*status)(const game_state *state);
695 bool can_print, can_print_in_colour; 744 bool can_print, can_print_in_colour;
696 void (*print_size)(const game_params *params, float *x, float *y); 745 void (*print_size)(const game_params *params, const game_ui *ui,
697 void (*print)(drawing *dr, const game_state *state, int tilesize); 746 float *x, float *y);
747 void (*print)(drawing *dr, const game_state *state, const game_ui *ui,
748 int tilesize);
698 bool wants_statusbar; 749 bool wants_statusbar;
699 bool is_timed; 750 bool is_timed;
700 bool (*timing_state)(const game_state *state, game_ui *ui); 751 bool (*timing_state)(const game_state *state, game_ui *ui);
@@ -712,7 +763,7 @@ struct drawing_api {
712 void (*draw_rect)(void *handle, int x, int y, int w, int h, int colour); 763 void (*draw_rect)(void *handle, int x, int y, int w, int h, int colour);
713 void (*draw_line)(void *handle, int x1, int y1, int x2, int y2, 764 void (*draw_line)(void *handle, int x1, int y1, int x2, int y2,
714 int colour); 765 int colour);
715 void (*draw_polygon)(void *handle, int *coords, int npoints, 766 void (*draw_polygon)(void *handle, const int *coords, int npoints,
716 int fillcolour, int outlinecolour); 767 int fillcolour, int outlinecolour);
717 void (*draw_circle)(void *handle, int cx, int cy, int radius, 768 void (*draw_circle)(void *handle, int cx, int cy, int radius,
718 int fillcolour, int outlinecolour); 769 int fillcolour, int outlinecolour);
@@ -750,17 +801,29 @@ struct drawing_api {
750#ifdef COMBINED 801#ifdef COMBINED
751extern const game *gamelist[]; 802extern const game *gamelist[];
752extern const int gamecount; 803extern const int gamecount;
804/* Also pre-declare every individual 'struct game' we expect */
805#define GAME(x) extern const game x;
806#include "generated-games.h"
807#undef GAME
753#else 808#else
754extern const game thegame; 809extern const game thegame;
755#endif 810#endif
756 811
757/* 812/*
758 * Special string value to return from interpret_move in the case 813 * Special string values to return from interpret_move.
759 * where the game UI has been updated but no actual move is being 814 *
760 * appended to the undo chain. Must be declared as a non-const char, 815 * MOVE_UI_UPDATE is for the case where the game UI has been updated
761 * but should never actually be modified by anyone. 816 * but no actual move is being appended to the undo chain.
817 *
818 * MOVE_NO_EFFECT is for when the key was understood by the puzzle,
819 * but it happens that there isn't effect, not even a UI change.
820 *
821 * MOVE_UNUSED is for keys that the puzzle has no use for at all.
822 *
823 * Each must be declared as a non-const char, but should never
824 * actually be modified by anyone.
762 */ 825 */
763extern char UI_UPDATE[]; 826extern char MOVE_UI_UPDATE[], MOVE_NO_EFFECT[], MOVE_UNUSED[];
764 827
765/* A little bit of help to lazy developers */ 828/* A little bit of help to lazy developers */
766#define DEFAULT_STATUSBAR_TEXT "Use status_bar() to fill this in." 829#define DEFAULT_STATUSBAR_TEXT "Use status_bar() to fill this in."