diff options
Diffstat (limited to 'apps/plugins/puzzles/src/netslide.c')
-rw-r--r-- | apps/plugins/puzzles/src/netslide.c | 105 |
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 | ||
898 | static bool game_can_format_as_text_now(const game_params *params) | ||
899 | { | ||
900 | return true; | ||
901 | } | ||
902 | |||
903 | static 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 | ||
994 | static char *encode_ui(const game_ui *ui) | ||
995 | { | ||
996 | return NULL; | ||
997 | } | ||
998 | |||
999 | static 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 | ||
1047 | static 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 | |||
1058 | static char *interpret_move(const game_state *state, game_ui *ui, | 1055 | static 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 | ||
1228 | static void game_compute_size(const game_params *params, int tilesize, | 1227 | static 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 | ||
1852 | static bool game_timing_state(const game_state *state, game_ui *ui) | ||
1853 | { | ||
1854 | return false; | ||
1855 | } | ||
1856 | |||
1857 | static void game_print_size(const game_params *params, float *x, float *y) | ||
1858 | { | ||
1859 | } | ||
1860 | |||
1861 | static 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 | ||