chiark / gitweb /
Add a request_keys() function with a midend wrapper.
authorFranklin Wei <me@fwei.tk>
Tue, 17 Apr 2018 20:18:16 +0000 (16:18 -0400)
committerSimon Tatham <anakin@pobox.com>
Sun, 22 Apr 2018 16:04:50 +0000 (17:04 +0100)
This function gives the front end a way to find out what keys the back
end requires; and as such it is mostly useful for ports without a
keyboard. It is based on changes originally found in Chris Boyle's
Android port, though some modifications were needed to make it more
flexible.

45 files changed:
blackbox.c
bridges.c
cube.c
devel.but
dominosa.c
fifteen.c
filling.c
flip.c
flood.c
galaxies.c
guess.c
inertia.c
keen.c
lightup.c
loopy.c
magnets.c
map.c
midend.c
mines.c
misc.c
net.c
netslide.c
nullgame.c
palisade.c
pattern.c
pearl.c
pegs.c
puzzles.h
range.c
rect.c
samegame.c
signpost.c
singles.c
sixteen.c
slant.c
solo.c
tents.c
towers.c
tracks.c
twiddle.c
undead.c
unequal.c
unfinished/group.c
unruly.c
untangle.c

index d92af92f2a81c0a4cc6234d9c4de214799e5a8da..881bf4a15dce59e229bf57f760d1d236083188c0 100644 (file)
@@ -1519,6 +1519,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 0a326f2a422a846546c838ca3cec0253c8569de4..098fea266512c5d93a926a54e47b9e0579b5dc32 100644 (file)
--- a/bridges.c
+++ b/bridges.c
@@ -3238,6 +3238,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/cube.c b/cube.c
index 2a79a81eef23ee204a2aa10bb5c3f24040e6d4be..749156564dcd72b65d5735c06cafe27b506e45df 100644 (file)
--- a/cube.c
+++ b/cube.c
@@ -1751,6 +1751,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 131678c17b85e99273a125ddcd95016b28038d4f..f30e8eecdadced29cad7a17fdcff9560ee47025a 100644 (file)
--- a/devel.but
+++ b/devel.but
@@ -1560,6 +1560,41 @@ the game was first completed (by setting a flag in
 freeze the timer thereafter so that the user can undo back through
 their solution process without altering their time.
 
+\S{backend-request-keys} \cw{request_keys()}
+
+\c key_label *(*request_keys)(const game_params *params, int *nkeys);
+
+This function returns a dynamically allocated array of \cw{key_label}
+items containing the buttons the back end deems absolutely
+\e{necessary} for gameplay, not an exhaustive list of every button the
+back end could accept. For example, Keen only returns the digits up to
+the game size and the backspace character, \cw{\\b}, even though it
+\e{could} accept \cw{M}, as only these buttons are actually needed to
+play the game. Each \cw{key_label} item contains the following fields:
+
+\c struct key_label {
+\c     const char *label; /* label for frontend use */
+\c     int button; /* button to pass to midend */
+\c } key_label;
+
+The \cw{label} field of this structure can (and often will) be set by
+the backend to \cw{NULL}, in which case the midend will instead call
+\c{button2label()} (\k{utils-button2label}) and fill in a generic
+label. The \cw{button} field is the associated code that can be passed
+to the midend when the frontend deems appropriate.
+
+The backend should set \cw{*nkeys} to the number of elements in the
+returned array.
+
+The field for this function point in the \cw{game} structure might be
+set to \cw{NULL} (and indeed it is for the majority of the games) to
+indicate that no additional buttons (apart from the cursor keys) are
+required to play the game.
+
+This function should not be called directly by frontends. Instead,
+frontends should use \cw{midend_request_keys()}
+(\k{midend-request-keys}).
+
 \S{backend-flags} \c{flags}
 
 \c int flags;
@@ -2998,6 +3033,18 @@ the effect of the keypress was to request termination of the
 program. A front end should shut down the puzzle in response to a
 zero return.
 
+\H{midend-request-keys} \cw{midend_request_keys()}
+
+\c key_label *midend_request_keys(midend *me, int *nkeys);
+
+This function behaves similarly to the backend's \cw{request_keys()}
+function (\k{backend-request-keys}). If the backend does not provide
+\cw{request_keys()}, this function will return \cw{NULL} and set
+\cw{*nkeys} to zero. Otherwise, this function will fill in the generic
+labels (i.e. the \cw{key_label} items that have their \cw{label}
+fields set to \cw{NULL}) by using \cw{button2label()}
+(\k{utils-button2label}).
+
 \H{midend-colours} \cw{midend_colours()}
 
 \c float *midend_colours(midend *me, int *ncolours);
@@ -4215,6 +4262,24 @@ Thus, \cw{ret[background*3]} to \cw{ret[background*3+2]} will be set
 to RGB values defining a sensible background colour, and similary
 \c{highlight} and \c{lowlight} will be set to sensible colours.
 
+\S{utils-button2label} \cw{button2label()}
+
+\c char *button2label(int button);
+
+This function generates a descriptive text label for \cw{button},
+which should be a button code that can be passed to the midend. For
+example, calling this function with \cw{CURSOR_UP} will result in the
+string \cw{"Up"}. This function should only be called when the
+\cw{key_label} item returned by a backend's \cw{request_keys()}
+(\k{backend-request-keys}) function has its \cw{label} field set to
+\cw{NULL}; in this case, the corresponding \cw{button} field can be
+passed to this function to obtain an appropriate label. If, however,
+the field is not \cw{NULL}, this function should not be called with
+the corresponding \cw{button} field.
+
+The returned string is dynamically allocated and should be
+\cw{sfree}'d by the caller.
+
 \C{writing} How to write a new puzzle
 
 This chapter gives a guide to how to actually write a new puzzle:
index a072ac6168ee5db5c45af442f619a79dc3d9c0bd..73b744d2bebfbfd7c56582cbe522f3971834f54f 100644 (file)
@@ -1723,6 +1723,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index f749e96b24814888a14c5fefd35073fe38c0129e..35bcb32a3688bed7061ed4ebf4a4ce73808663a5 100644 (file)
--- a/fifteen.c
+++ b/fifteen.c
@@ -1103,6 +1103,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 231de4c0799c91fe075054e77f2bc566ff918be4..db6f95d26f8b577d9f41dd2f1ca3d35779584833 100644 (file)
--- a/filling.c
+++ b/filling.c
@@ -1287,6 +1287,24 @@ static const char *validate_desc(const game_params *params, const char *desc)
     return (area < sz) ? "Not enough data to fill grid" : NULL;
 }
 
+static key_label *game_request_keys(const game_params *params, int *nkeys)
+{
+    key_label *keys = snewn(11, key_label);
+    *nkeys = 11;
+
+    int i;
+
+    for(i = 0; i < 10; ++i)
+    {
+       keys[i].button = '0' + i;
+       keys[i].label = NULL;
+    }
+    keys[10].button = '\b';
+    keys[10].label = NULL;
+
+    return keys;
+}
+
 static game_state *new_game(midend *me, const game_params *params,
                             const char *desc)
 {
@@ -2125,6 +2143,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    game_request_keys,
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/flip.c b/flip.c
index 9e5716a118318c1478c061956f707f3c01bb5c37..481c4b5ec3e33b89f705c7239ed2e592a5d5f42f 100644 (file)
--- a/flip.c
+++ b/flip.c
@@ -1327,6 +1327,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/flood.c b/flood.c
index a3a2506482fa2baeaa7bc92674223d084f708086..99bbae39844302321a7d8c8c50efae6e9b17cfa7 100644 (file)
--- a/flood.c
+++ b/flood.c
@@ -1348,6 +1348,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 5d7dbdf93321c714b52f618457c4b17c51071010..11efd34d44aad68b4b5b5939ba11c6d0a2cf318a 100644 (file)
@@ -3652,6 +3652,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/guess.c b/guess.c
index a14f3bdc4de61852582f6e2f700c4c39fa5bfe33..98019d272b4b50dba4b05aa951bbe3cc1686f45c 100644 (file)
--- a/guess.c
+++ b/guess.c
@@ -1493,6 +1493,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index ad58bd2ae96012b30cb065d59ca5376272849bb2..6963dee7f7b0ce1219a40ee51b8001de821006d1 100644 (file)
--- a/inertia.c
+++ b/inertia.c
@@ -2229,6 +2229,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/keen.c b/keen.c
index ec7af12985c46d5ea4da5339b4f40294e8e4f67b..1e531d9905a74852e330671cff144a45e76d3ff0 100644 (file)
--- a/keen.c
+++ b/keen.c
@@ -1251,6 +1251,27 @@ static const char *validate_desc(const game_params *params, const char *desc)
     return NULL;
 }
 
+static key_label *game_request_keys(const game_params *params, int *nkeys)
+{
+    int i;
+    int w = params->w;
+
+    key_label *keys = snewn(w+1, key_label);
+    *nkeys = w + 1;
+
+    for (i = 0; i < w; i++) {
+        if (i<9) keys[i].button = '1' + i;
+        else keys[i].button = 'a' + i - 9;
+
+        keys[i].label = NULL;
+    }
+    keys[w].button = '\b';
+    keys[w].label = NULL;
+
+
+    return keys;
+}
+
 static game_state *new_game(midend *me, const game_params *params,
                             const char *desc)
 {
@@ -2354,6 +2375,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    game_request_keys,
     game_changed_state,
     interpret_move,
     execute_move,
index fd363e076e2e6c1db7e8e47871792cd475139102..acee8533668b19ece76ff9bf47bbf300b6d514fc 100644 (file)
--- a/lightup.c
+++ b/lightup.c
@@ -2303,6 +2303,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/loopy.c b/loopy.c
index c14412d6bec10dee8a7531207b09a2f9d2138a38..f5f89170527280a52a81f4215b78ed59dfca8738 100644 (file)
--- a/loopy.c
+++ b/loopy.c
@@ -3658,6 +3658,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index ebb537663ae359fb8fff98aa3825c955c6d41928..c9f97b63dd6d024661dd68f8f012aa49288d47c9 100644 (file)
--- a/magnets.c
+++ b/magnets.c
@@ -2409,6 +2409,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/map.c b/map.c
index ffd21236b0bc646ba28c1d19d97775fa79d2f0e2..ccec1277835c4e1e8cec5cd60d222996f8dcd478 100644 (file)
--- a/map.c
+++ b/map.c
@@ -3236,6 +3236,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 99112fa7858245e80bc0265761d87e1fe7ed6034..1a08ef690df27fc2d036d440b83899c1054c361c 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -1104,6 +1104,27 @@ int midend_process_key(midend *me, int x, int y, int button)
     return ret;
 }
 
+key_label *midend_request_keys(midend *me, int *n)
+{
+    key_label *keys = NULL;
+    int nkeys = 0, i;
+
+    if(me->ourgame->request_keys)
+    {
+        keys = me->ourgame->request_keys(midend_get_params(me), &nkeys);
+        for(i = 0; i < nkeys; ++i)
+        {
+            if(!keys[i].label)
+                keys[i].label = button2label(keys[i].button);
+        }
+    }
+
+    if(n)
+        *n = nkeys;
+
+    return keys;
+}
+
 void midend_redraw(midend *me)
 {
     assert(me->drawing);
diff --git a/mines.c b/mines.c
index 6a854c6aac364c098c0659d95c01640ec8b80f9d..e606735394ea30b7692d7b32db20aec173fb83b5 100644 (file)
--- a/mines.c
+++ b/mines.c
@@ -3191,6 +3191,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/misc.c b/misc.c
index 852f86902397fa739c6d0d9c35c3bda45b43d468..917958aa313f2aa9f9d685d9e936152e560676fa 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -21,6 +21,15 @@ void free_cfg(config_item *cfg)
     sfree(cfg);
 }
 
+void free_keys(key_label *keys, int nkeys)
+{
+    int i;
+
+    for(i = 0; i < nkeys; i++)
+        sfree(keys->label);
+    sfree(keys);
+}
+
 /*
  * The Mines (among others) game descriptions contain the location of every
  * mine, and can therefore be used to cheat.
@@ -393,4 +402,40 @@ void copy_left_justified(char *buf, size_t sz, const char *str)
     buf[sz - 1] = 0;
 }
 
+/* Returns a dynamically allocated label for a generic button.
+ * Game-specific buttons should go into the `label' field of key_label
+ * instead. */
+char *button2label(int button)
+{
+    /* check if it's a keyboard button */
+    if(('A' <= button && button <= 'Z') ||
+       ('a' <= button && button <= 'z') ||
+       ('0' <= button && button <= '9') )
+    {
+        char str[2] = { button, '\0' };
+        return dupstr(str);
+    }
+
+    switch(button)
+    {
+    case CURSOR_UP:
+        return dupstr("Up");
+    case CURSOR_DOWN:
+        return dupstr("Down");
+    case CURSOR_LEFT:
+        return dupstr("Left");
+    case CURSOR_RIGHT:
+        return dupstr("Right");
+    case CURSOR_SELECT:
+        return dupstr("Select");
+    case '\b':
+        return dupstr("Clear");
+    default:
+        fatal("unknown generic key");
+    }
+
+    /* should never get here */
+    return NULL;
+}
+
 /* vim: set shiftwidth=4 tabstop=8: */
diff --git a/net.c b/net.c
index 20366a2b7a173d66d90ed27b0c3885b00af0f212..f26b5d7206fad0d82f67dab42ab1df0491e77e05 100644 (file)
--- a/net.c
+++ b/net.c
@@ -3236,6 +3236,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index aee597381b7364aea9108244b42f25349e25cee9..bb0ed1ec1762c1a358ed70a6a0349f7c6066b15e 100644 (file)
@@ -1866,6 +1866,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index bc19c1e6f054d39dddc49d1f2c927fe89ab00c9a..13c464c60dedac84a16d8676b1762e9bf91e3fc6 100644 (file)
@@ -285,6 +285,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 5227a1d56c18f2b471d4836d1080f3cd95c3d8d5..34257eb26ef3df044edf73b494a82ec33723738a 100644 (file)
@@ -1375,6 +1375,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 45b1b0c1582d6faa0a270fe9a15befafeaf7840f..632a9867d2f751e66a2555e09d3f7cc56a75c943 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -1998,6 +1998,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/pearl.c b/pearl.c
index 4f3be50275b1cc32e0dd2d785e56c1d6ca0f3d6f..07949b5a99d45bcfa1961713235c45d19b5e7edc 100644 (file)
--- a/pearl.c
+++ b/pearl.c
@@ -2621,6 +2621,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/pegs.c b/pegs.c
index 565ba9417f111852936c210456c308ed2cdb5568..823d5c2866430f475c9a4b85c28ac64c80c80a73 100644 (file)
--- a/pegs.c
+++ b/pegs.c
@@ -1316,6 +1316,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 6b6e6b39c60cb6240c3c20595f67936fa14a4dca..2eb7647022038a26f767e5640d3cef46ddd84f2d 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -217,6 +217,24 @@ void preset_menu_add_preset(struct preset_menu *menu,
  * want to organise their preset menu usage */
 game_params *preset_menu_lookup_by_id(struct preset_menu *menu, int id);
 
+/*
+ * Small structure specifying a UI button in a keyboardless front
+ * end. The button will have the text of "label" written on it, and
+ * pressing it causes the value "button" to be passed to
+ * midend_process_key() as if typed at the keyboard.
+ *
+ * If `label' is NULL (which it likely will be), a generic label can
+ * be generated with the button2label() function.
+ */
+typedef struct key_label {
+    /* What should be displayed to the user by the frontend. Backends
+     * can set this field to NULL and have it filled in by the midend
+     * with a generic label. Dynamically allocated, but frontends
+     * should probably use free_keys() to free instead. */
+    char *label;
+    int button; /* passed to midend_process_key when button is pressed */
+} key_label;
+
 /*
  * Platform routines
  */
@@ -301,6 +319,7 @@ void midend_new_game(midend *me);
 void midend_restart_game(midend *me);
 void midend_stop_anim(midend *me);
 int midend_process_key(midend *me, int x, int y, int button);
+key_label *midend_request_keys(midend *me, int *nkeys);
 void midend_force_redraw(midend *me);
 void midend_redraw(midend *me);
 float *midend_colours(midend *me, int *ncolours);
@@ -356,6 +375,7 @@ char *dupstr(const char *s);
  * misc.c
  */
 void free_cfg(config_item *cfg);
+void free_keys(key_label *keys, int nkeys);
 void obfuscate_bitmap(unsigned char *bmp, int bits, int decode);
 char *fgetline(FILE *fp);
 
@@ -400,6 +420,11 @@ void draw_text_outline(drawing *dr, int x, int y, int fonttype,
  * less than buffer size. */
 void copy_left_justified(char *buf, size_t sz, const char *str);
 
+/* Returns a generic label based on the value of `button.' To be used
+   whenever a `label' field returned by the request_keys() game
+   function is NULL. Dynamically allocated, to be freed by caller. */
+char *button2label(int button);
+
 /*
  * dsf.c
  */
@@ -610,6 +635,7 @@ struct game {
     void (*free_ui)(game_ui *ui);
     char *(*encode_ui)(const game_ui *ui);
     void (*decode_ui)(game_ui *ui, const char *encoding);
+    key_label *(*request_keys)(const game_params *params, int *nkeys);
     void (*changed_state)(game_ui *ui, const game_state *oldstate,
                           const game_state *newstate);
     char *(*interpret_move)(const game_state *state, game_ui *ui,
diff --git a/range.c b/range.c
index 58d6e48f19f8f07243c4be8d829d1d0dcd151160..03bdf6d5fd689c89942f5968c3959763a7996835 100644 (file)
--- a/range.c
+++ b/range.c
@@ -1813,6 +1813,7 @@ struct game const thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/rect.c b/rect.c
index 01408082a4b28cafe3f65a13a2c6d9b1bb43113f..c3092f2e09a356ade592c181a28d1d0b152b8361 100644 (file)
--- a/rect.c
+++ b/rect.c
@@ -2974,6 +2974,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index d7d06764bfa40f5814c6ed9b492b9e01218fb1bb..4dfc302000cb2441e39d68315877a7249dfd796c 100644 (file)
@@ -1656,6 +1656,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 72f3ab201f16943ca52cd1752af1bac120ec09fe..47da97f53f0c5832551e8a14f9a22f04fe966254 100644 (file)
@@ -2246,6 +2246,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 5929d829327acc937a16f9847b40c4b676e7c27c..35c5fcee59bff906809e762406cc6719c1528d8f 100644 (file)
--- a/singles.c
+++ b/singles.c
@@ -1828,6 +1828,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 70cc43339a4a67b78fe2bada9c8c29446e824c63..b027e0b75a2b58cbf15104bba7c0fdaf6bd94555 100644 (file)
--- a/sixteen.c
+++ b/sixteen.c
@@ -1188,6 +1188,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/slant.c b/slant.c
index 3fd66115b15f36aeeaedb30a9c8950c0f0575ea7..5eeb66841cb538e3c200750c5ed3a879852bca7f 100644 (file)
--- a/slant.c
+++ b/slant.c
@@ -2164,6 +2164,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/solo.c b/solo.c
index dae099834fce1a8ca6b6f0ca1cd0ec31f0780f8e..69fd85b90be699118133518d297dd0633117af71 100644 (file)
--- a/solo.c
+++ b/solo.c
@@ -3608,6 +3608,26 @@ static struct block_structure *gen_killer_cages(int cr, random_state *rs,
     return b;
 }
 
+static key_label *game_request_keys(const game_params *params, int *nkeys)
+{
+    int i;
+    int cr = params->c * params->r;
+    key_label *keys = snewn(cr+1, key_label);
+    *nkeys = cr + 1;
+
+    for (i = 0; i < cr; i++) {
+        if (i<9) keys[i].button = '1' + i;
+        else keys[i].button = 'a' + i - 9;
+
+        keys[i].label = NULL;
+    }
+    keys[cr].button = '\b';
+    keys[cr].label = NULL;
+
+
+    return keys;
+}
+
 static char *new_game_desc(const game_params *params, random_state *rs,
                           char **aux, int interactive)
 {
@@ -5579,6 +5599,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    game_request_keys,
     game_changed_state,
     interpret_move,
     execute_move,
diff --git a/tents.c b/tents.c
index 696eec1ae1d1e6d15c9b7be30594518ac3cb2a74..2f0977efbeec9a7ad3835768c0f371394f5273f2 100644 (file)
--- a/tents.c
+++ b/tents.c
@@ -2613,6 +2613,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 30ee4cb1eb1ccfcf5cf950506ba0c0555d02863b..d90167b0d8dcb866e9a344e8a0956c6e8cf30209 100644 (file)
--- a/towers.c
+++ b/towers.c
@@ -864,6 +864,25 @@ static const char *validate_desc(const game_params *params, const char *desc)
     return NULL;
 }
 
+static key_label *game_request_keys(const game_params *params, int *nkeys)
+{
+    int i;
+    int w = params->w;
+    key_label *keys = snewn(w+1, key_label);
+    *nkeys = w + 1;
+
+    for (i = 0; i < w; i++) {
+       if (i<9) keys[i].button = '1' + i;
+       else keys[i].button = 'a' + i - 9;
+
+        keys[i].label = NULL;
+    }
+    keys[w].button = '\b';
+    keys[w].label = NULL;
+
+    return keys;
+}
+
 static game_state *new_game(midend *me, const game_params *params,
                             const char *desc)
 {
@@ -1993,6 +2012,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    game_request_keys,
     game_changed_state,
     interpret_move,
     execute_move,
index b05fbd232c184042b6f2e892efcb2000c38f3d4f..4e22c9789859ffb13ff4c211d2e268b680181403 100644 (file)
--- a/tracks.c
+++ b/tracks.c
@@ -2646,6 +2646,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 1f2825f2d82e6187b1f39a00fa2811aaf7dc5fab..f84d0cb9751697298d7e8effc226784bf10a36e1 100644 (file)
--- a/twiddle.c
+++ b/twiddle.c
@@ -1291,6 +1291,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index df0735e4690773bf46e44adfdc5a8aaf257656b5..03b014f5a154e0470ca7d5d80b59849a919329e9 100644 (file)
--- a/undead.c
+++ b/undead.c
@@ -1314,6 +1314,26 @@ void num2grid(int num, int width, int height, int *x, int *y) {
     return;
 }
 
+static key_label *game_request_keys(const game_params *params, int *nkeys)
+{
+    key_label *keys = snewn(4, key_label);
+    *nkeys = 4;
+
+    keys[0].button = 'G';
+    keys[0].label = dupstr("Ghost");
+
+    keys[1].button = 'V';
+    keys[1].label = dupstr("Vampire");
+
+    keys[2].button = 'Z';
+    keys[2].label = dupstr("Zombie");
+
+    keys[3].button = '\b';
+    keys[3].label = NULL;
+
+    return keys;
+}
+
 static game_state *new_game(midend *me, const game_params *params,
                             const char *desc)
 {
@@ -2716,6 +2736,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    game_request_keys,
     game_changed_state,
     interpret_move,
     execute_move,
index cb477c9e37af3fd8ffbcc4d67e6f72a6912c95e0..b87415b9fbaac28f22eaca9db68d0b61b6080bcb 100644 (file)
--- a/unequal.c
+++ b/unequal.c
@@ -1280,6 +1280,25 @@ fail:
     return NULL;
 }
 
+static key_label *game_request_keys(const game_params *params, int *nkeys)
+{
+    int order = params->order;
+    char off = (order > 9) ? '0' : '1';
+    key_label *keys = snewn(order + 1, key_label);
+    *nkeys = order + 1;
+
+    int i;
+    for(i = 0; i < order; i++) {
+        if (i==10) off = 'a'-10;
+        keys[i].button = i + off;
+        keys[i].label = NULL;
+    }
+    keys[order].button = '\b';
+    keys[order].label = NULL;
+
+    return keys;
+}
+
 static game_state *new_game(midend *me, const game_params *params,
                             const char *desc)
 {
@@ -2011,6 +2030,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    game_request_keys,
     game_changed_state,
     interpret_move,
     execute_move,
index b812b041ebffd683a76048d68c813065d1eb856f..72293dd4eaf6b2ee6f202b1b2b0a39e7d569a5fa 100644 (file)
@@ -2081,6 +2081,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index 9d2d5924d23f51d70e9bf3fc6a80a6a8ace01638..b3057a72987eeaa173e6b57c7c85d638e3423a2c 100644 (file)
--- a/unruly.c
+++ b/unruly.c
@@ -1926,6 +1926,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,
index a693378570bb4621ca13f32f7dcab1dce008e753..b71cfa7bb51c59090a3b00398ac6b8e5f1866dbd 100644 (file)
@@ -1470,6 +1470,7 @@ const struct game thegame = {
     free_ui,
     encode_ui,
     decode_ui,
+    NULL, /* game_request_keys */
     game_changed_state,
     interpret_move,
     execute_move,