summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/netslide.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/netslide.c')
-rw-r--r--apps/plugins/puzzles/src/netslide.c105
1 files changed, 42 insertions, 63 deletions
diff --git a/apps/plugins/puzzles/src/netslide.c b/apps/plugins/puzzles/src/netslide.c
index 14af2a689d..4e6e82b39f 100644
--- a/apps/plugins/puzzles/src/netslide.c
+++ b/apps/plugins/puzzles/src/netslide.c
@@ -8,7 +8,12 @@
8#include <string.h> 8#include <string.h>
9#include <assert.h> 9#include <assert.h>
10#include <ctype.h> 10#include <ctype.h>
11#include <math.h> 11#include <limits.h>
12#ifdef NO_TGMATH_H
13# include <math.h>
14#else
15# include <tgmath.h>
16#endif
12 17
13#include "puzzles.h" 18#include "puzzles.h"
14#include "tree234.h" 19#include "tree234.h"
@@ -242,10 +247,7 @@ static char *encode_params(const game_params *params, bool full)
242 if (params->wrapping) 247 if (params->wrapping)
243 ret[len++] = 'w'; 248 ret[len++] = 'w';
244 if (full && params->barrier_probability) 249 if (full && params->barrier_probability)
245 { 250 len += sprintf(ret+len, "b%g", params->barrier_probability);
246 len += sprintf(ret+len, "b");
247 len += ftoa(ret + len, params->barrier_probability);
248 }
249 /* Shuffle limit is part of the limited parameters, because we have to 251 /* Shuffle limit is part of the limited parameters, because we have to
250 * provide the target move count. */ 252 * provide the target move count. */
251 if (params->movetarget) 253 if (params->movetarget)
@@ -279,7 +281,7 @@ static config_item *game_configure(const game_params *params)
279 281
280 ret[3].name = "Barrier probability"; 282 ret[3].name = "Barrier probability";
281 ret[3].type = C_STRING; 283 ret[3].type = C_STRING;
282 ftoa(buf, params->barrier_probability); 284 sprintf(buf, "%g", params->barrier_probability);
283 ret[3].u.string.sval = dupstr(buf); 285 ret[3].u.string.sval = dupstr(buf);
284 286
285 ret[4].name = "Number of shuffling moves"; 287 ret[4].name = "Number of shuffling moves";
@@ -310,6 +312,8 @@ static const char *validate_params(const game_params *params, bool full)
310{ 312{
311 if (params->width <= 1 || params->height <= 1) 313 if (params->width <= 1 || params->height <= 1)
312 return "Width and height must both be greater than one"; 314 return "Width and height must both be greater than one";
315 if (params->width > INT_MAX / params->height)
316 return "Width times height must not be unreasonably large";
313 if (params->barrier_probability < 0) 317 if (params->barrier_probability < 0)
314 return "Barrier probability may not be negative"; 318 return "Barrier probability may not be negative";
315 if (params->barrier_probability > 1) 319 if (params->barrier_probability > 1)
@@ -895,16 +899,6 @@ static char *solve_game(const game_state *state, const game_state *currstate,
895 return dupstr(aux); 899 return dupstr(aux);
896} 900}
897 901
898static bool game_can_format_as_text_now(const game_params *params)
899{
900 return true;
901}
902
903static char *game_text_format(const game_state *state)
904{
905 return NULL;
906}
907
908/* ---------------------------------------------------------------------- 902/* ----------------------------------------------------------------------
909 * Utility routine. 903 * Utility routine.
910 */ 904 */
@@ -981,7 +975,7 @@ static game_ui *new_ui(const game_state *state)
981 game_ui *ui = snew(game_ui); 975 game_ui *ui = snew(game_ui);
982 ui->cur_x = 0; 976 ui->cur_x = 0;
983 ui->cur_y = -1; 977 ui->cur_y = -1;
984 ui->cur_visible = false; 978 ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false);
985 979
986 return ui; 980 return ui;
987} 981}
@@ -991,15 +985,6 @@ static void free_ui(game_ui *ui)
991 sfree(ui); 985 sfree(ui);
992} 986}
993 987
994static char *encode_ui(const game_ui *ui)
995{
996 return NULL;
997}
998
999static void decode_ui(game_ui *ui, const char *encoding)
1000{
1001}
1002
1003/* ---------------------------------------------------------------------- 988/* ----------------------------------------------------------------------
1004 * Process a move. 989 * Process a move.
1005 */ 990 */
@@ -1009,7 +994,9 @@ static void slide_row_int(int w, int h, unsigned char *tiles, int dir, int row)
1009 int x = dir > 0 ? -1 : w; 994 int x = dir > 0 ? -1 : w;
1010 int tx = x + dir; 995 int tx = x + dir;
1011 int n = w - 1; 996 int n = w - 1;
1012 unsigned char endtile = tiles[row * w + tx]; 997 unsigned char endtile;
998 assert(0 <= tx && tx < w);
999 endtile = tiles[row * w + tx];
1013 do { 1000 do {
1014 x = tx; 1001 x = tx;
1015 tx = (x + dir + w) % w; 1002 tx = (x + dir + w) % w;
@@ -1023,7 +1010,9 @@ static void slide_col_int(int w, int h, unsigned char *tiles, int dir, int col)
1023 int y = dir > 0 ? -1 : h; 1010 int y = dir > 0 ? -1 : h;
1024 int ty = y + dir; 1011 int ty = y + dir;
1025 int n = h - 1; 1012 int n = h - 1;
1026 unsigned char endtile = tiles[ty * w + col]; 1013 unsigned char endtile;
1014 assert(0 <= ty && ty < h);
1015 endtile = tiles[ty * w + col];
1027 do { 1016 do {
1028 y = ty; 1017 y = ty;
1029 ty = (y + dir + h) % h; 1018 ty = (y + dir + h) % h;
@@ -1055,6 +1044,14 @@ struct game_drawstate {
1055 int cur_x, cur_y; 1044 int cur_x, cur_y;
1056}; 1045};
1057 1046
1047static const char *current_key_label(const game_ui *ui,
1048 const game_state *state, int button)
1049{
1050 if (IS_CURSOR_SELECT(button) && ui->cur_visible)
1051 return "Slide";
1052 return "";
1053}
1054
1058static char *interpret_move(const game_state *state, game_ui *ui, 1055static char *interpret_move(const game_state *state, game_ui *ui,
1059 const game_drawstate *ds, 1056 const game_drawstate *ds,
1060 int x, int y, int button) 1057 int x, int y, int button)
@@ -1063,7 +1060,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1063 int dx, dy; 1060 int dx, dy;
1064 char buf[80]; 1061 char buf[80];
1065 1062
1066 button &= ~MOD_MASK; 1063 button = STRIP_BUTTON_MODIFIERS(button);
1067 1064
1068 if (IS_CURSOR_MOVE(button)) { 1065 if (IS_CURSOR_MOVE(button)) {
1069 int cpos, diff = 0; 1066 int cpos, diff = 0;
@@ -1078,7 +1075,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1078 } 1075 }
1079 1076
1080 ui->cur_visible = true; 1077 ui->cur_visible = true;
1081 return UI_UPDATE; 1078 return MOVE_UI_UPDATE;
1082 } 1079 }
1083 1080
1084 if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { 1081 if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
@@ -1092,7 +1089,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
1092 } else { 1089 } else {
1093 /* 'click' when cursor is invisible just makes cursor visible. */ 1090 /* 'click' when cursor is invisible just makes cursor visible. */
1094 ui->cur_visible = true; 1091 ui->cur_visible = true;
1095 return UI_UPDATE; 1092 return MOVE_UI_UPDATE;
1096 } 1093 }
1097 } else 1094 } else
1098 return NULL; 1095 return NULL;
@@ -1136,7 +1133,9 @@ static game_state *execute_move(const game_state *from, const char *move)
1136 1133
1137 if ((move[0] == 'C' || move[0] == 'R') && 1134 if ((move[0] == 'C' || move[0] == 'R') &&
1138 sscanf(move+1, "%d,%d", &c, &d) == 2 && 1135 sscanf(move+1, "%d,%d", &c, &d) == 2 &&
1139 c >= 0 && c < (move[0] == 'C' ? from->width : from->height)) { 1136 c >= 0 && c < (move[0] == 'C' ? from->width : from->height) &&
1137 d <= (move[0] == 'C' ? from->height : from->width) &&
1138 d >= -(move[0] == 'C' ? from->height : from->width) && d != 0) {
1140 col = (move[0] == 'C'); 1139 col = (move[0] == 'C');
1141 } else if (move[0] == 'S' && 1140 } else if (move[0] == 'S' &&
1142 strlen(move) == from->width * from->height + 1) { 1141 strlen(move) == from->width * from->height + 1) {
@@ -1226,7 +1225,7 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds)
1226} 1225}
1227 1226
1228static void game_compute_size(const game_params *params, int tilesize, 1227static void game_compute_size(const game_params *params, int tilesize,
1229 int *x, int *y) 1228 const game_ui *ui, int *x, int *y)
1230{ 1229{
1231 /* Ick: fake up `ds->tilesize' for macro expansion purposes */ 1230 /* Ick: fake up `ds->tilesize' for macro expansion purposes */
1232 struct { int tilesize; } ads, *ds = &ads; 1231 struct { int tilesize; } ads, *ds = &ads;
@@ -1490,7 +1489,7 @@ static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state,
1490 vx = (dy ? 1 : 0); 1489 vx = (dy ? 1 : 0);
1491 vy = (dx ? 1 : 0); 1490 vy = (dx ? 1 : 0);
1492 1491
1493 if (xshift == 0.0 && yshift == 0.0 && (tile & dir)) { 1492 if (xshift == 0.0F && yshift == 0.0F && (tile & dir)) {
1494 /* 1493 /*
1495 * If we are fully connected to the other tile, we must 1494 * If we are fully connected to the other tile, we must
1496 * draw right across the tile border. (We can use our 1495 * draw right across the tile border. (We can use our
@@ -1594,22 +1593,13 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
1594 int cur_x = -1, cur_y = -1; 1593 int cur_x = -1, cur_y = -1;
1595 1594
1596 /* 1595 /*
1597 * Clear the screen and draw the exterior barrier lines if this 1596 * Draw the exterior barrier lines if this is our first call.
1598 * is our first call.
1599 */ 1597 */
1600 if (!ds->started) { 1598 if (!ds->started) {
1601 int phase; 1599 int phase;
1602 1600
1603 ds->started = true; 1601 ds->started = true;
1604 1602
1605 draw_rect(dr, 0, 0,
1606 BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * state->width + TILE_BORDER,
1607 BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * state->height + TILE_BORDER,
1608 COL_BACKGROUND);
1609 draw_update(dr, 0, 0,
1610 BORDER * 2 + WINDOW_OFFSET*2 + TILE_SIZE*state->width + TILE_BORDER,
1611 BORDER * 2 + WINDOW_OFFSET*2 + TILE_SIZE*state->height + TILE_BORDER);
1612
1613 for (phase = 0; phase < 2; phase++) { 1603 for (phase = 0; phase < 2; phase++) {
1614 1604
1615 for (x = 0; x < ds->width; x++) { 1605 for (x = 0; x < ds->width; x++) {
@@ -1703,7 +1693,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
1703 /* 1693 /*
1704 * Draw any tile which differs from the way it was last drawn. 1694 * Draw any tile which differs from the way it was last drawn.
1705 */ 1695 */
1706 if (xshift != 0.0 || yshift != 0.0) { 1696 if (xshift != 0.0F || yshift != 0.0F) {
1707 active = compute_active(state, 1697 active = compute_active(state,
1708 state->last_move_row, state->last_move_col); 1698 state->last_move_row, state->last_move_col);
1709 } else { 1699 } else {
@@ -1849,19 +1839,6 @@ static int game_status(const game_state *state)
1849 return state->completed ? +1 : 0; 1839 return state->completed ? +1 : 0;
1850} 1840}
1851 1841
1852static bool game_timing_state(const game_state *state, game_ui *ui)
1853{
1854 return false;
1855}
1856
1857static void game_print_size(const game_params *params, float *x, float *y)
1858{
1859}
1860
1861static void game_print(drawing *dr, const game_state *state, int tilesize)
1862{
1863}
1864
1865#ifdef COMBINED 1842#ifdef COMBINED
1866#define thegame netslide 1843#define thegame netslide
1867#endif 1844#endif
@@ -1882,13 +1859,15 @@ const struct game thegame = {
1882 dup_game, 1859 dup_game,
1883 free_game, 1860 free_game,
1884 true, solve_game, 1861 true, solve_game,
1885 false, game_can_format_as_text_now, game_text_format, 1862 false, NULL, NULL, /* can_format_as_text_now, text_format */
1863 NULL, NULL, /* get_prefs, set_prefs */
1886 new_ui, 1864 new_ui,
1887 free_ui, 1865 free_ui,
1888 encode_ui, 1866 NULL, /* encode_ui */
1889 decode_ui, 1867 NULL, /* decode_ui */
1890 NULL, /* game_request_keys */ 1868 NULL, /* game_request_keys */
1891 game_changed_state, 1869 game_changed_state,
1870 current_key_label,
1892 interpret_move, 1871 interpret_move,
1893 execute_move, 1872 execute_move,
1894 PREFERRED_TILE_SIZE, game_compute_size, game_set_size, 1873 PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
@@ -1900,9 +1879,9 @@ const struct game thegame = {
1900 game_flash_length, 1879 game_flash_length,
1901 game_get_cursor_location, 1880 game_get_cursor_location,
1902 game_status, 1881 game_status,
1903 false, false, game_print_size, game_print, 1882 false, false, NULL, NULL, /* print_size, print */
1904 true, /* wants_statusbar */ 1883 true, /* wants_statusbar */
1905 false, game_timing_state, 1884 false, NULL, /* timing_state */
1906 0, /* flags */ 1885 0, /* flags */
1907}; 1886};
1908 1887