summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/twiddle.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/twiddle.c')
-rw-r--r--apps/plugins/puzzles/src/twiddle.c108
1 files changed, 40 insertions, 68 deletions
diff --git a/apps/plugins/puzzles/src/twiddle.c b/apps/plugins/puzzles/src/twiddle.c
index a107925aee..49d8db7825 100644
--- a/apps/plugins/puzzles/src/twiddle.c
+++ b/apps/plugins/puzzles/src/twiddle.c
@@ -10,7 +10,12 @@
10#include <string.h> 10#include <string.h>
11#include <assert.h> 11#include <assert.h>
12#include <ctype.h> 12#include <ctype.h>
13#include <math.h> 13#include <limits.h>
14#ifdef NO_TGMATH_H
15# include <math.h>
16#else
17# include <tgmath.h>
18#endif
14 19
15#include "puzzles.h" 20#include "puzzles.h"
16 21
@@ -123,14 +128,16 @@ static void decode_params(game_params *ret, char const *string)
123 while (*string) { 128 while (*string) {
124 if (*string == 'r') { 129 if (*string == 'r') {
125 ret->rowsonly = true; 130 ret->rowsonly = true;
131 string++;
126 } else if (*string == 'o') { 132 } else if (*string == 'o') {
127 ret->orientable = true; 133 ret->orientable = true;
134 string++;
128 } else if (*string == 'm') { 135 } else if (*string == 'm') {
129 string++; 136 string++;
130 ret->movetarget = atoi(string); 137 ret->movetarget = atoi(string);
131 while (string[1] && isdigit((unsigned char)string[1])) string++; 138 while (*string && isdigit((unsigned char)*string)) string++;
132 } 139 } else
133 string++; 140 string++;
134 } 141 }
135} 142}
136 143
@@ -210,6 +217,8 @@ static const char *validate_params(const game_params *params, bool full)
210 return "Width must be at least the rotating block size"; 217 return "Width must be at least the rotating block size";
211 if (params->h < params->n) 218 if (params->h < params->n)
212 return "Height must be at least the rotating block size"; 219 return "Height must be at least the rotating block size";
220 if (params->w > INT_MAX / params->h)
221 return "Width times height must not be unreasonably large";
213 if (params->movetarget < 0) 222 if (params->movetarget < 0)
214 return "Number of shuffling moves may not be negative"; 223 return "Number of shuffling moves may not be negative";
215 return NULL; 224 return NULL;
@@ -523,18 +532,6 @@ static void free_game(game_state *state)
523 sfree(state); 532 sfree(state);
524} 533}
525 534
526static int compare_int(const void *av, const void *bv)
527{
528 const int *a = (const int *)av;
529 const int *b = (const int *)bv;
530 if (*a < *b)
531 return -1;
532 else if (*a > *b)
533 return +1;
534 else
535 return 0;
536}
537
538static char *solve_game(const game_state *state, const game_state *currstate, 535static char *solve_game(const game_state *state, const game_state *currstate,
539 const char *aux, const char **error) 536 const char *aux, const char **error)
540{ 537{
@@ -615,7 +612,7 @@ static game_ui *new_ui(const game_state *state)
615 612
616 ui->cur_x = 0; 613 ui->cur_x = 0;
617 ui->cur_y = 0; 614 ui->cur_y = 0;
618 ui->cur_visible = false; 615 ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false);
619 616
620 return ui; 617 return ui;
621} 618}
@@ -625,18 +622,20 @@ static void free_ui(game_ui *ui)
625 sfree(ui); 622 sfree(ui);
626} 623}
627 624
628static char *encode_ui(const game_ui *ui) 625static void game_changed_state(game_ui *ui, const game_state *oldstate,
629{ 626 const game_state *newstate)
630 return NULL;
631}
632
633static void decode_ui(game_ui *ui, const char *encoding)
634{ 627{
635} 628}
636 629
637static void game_changed_state(game_ui *ui, const game_state *oldstate, 630static const char *current_key_label(const game_ui *ui,
638 const game_state *newstate) 631 const game_state *state, int button)
639{ 632{
633 if (!ui->cur_visible) return "";
634 switch (button) {
635 case CURSOR_SELECT: return "Turn left";
636 case CURSOR_SELECT2: return "Turn right";
637 }
638 return "";
640} 639}
641 640
642struct game_drawstate { 641struct game_drawstate {
@@ -657,18 +656,9 @@ static char *interpret_move(const game_state *state, game_ui *ui,
657 656
658 button = button & (~MOD_MASK | MOD_NUM_KEYPAD); 657 button = button & (~MOD_MASK | MOD_NUM_KEYPAD);
659 658
660 if (IS_CURSOR_MOVE(button)) { 659 if (IS_CURSOR_MOVE(button))
661 if (button == CURSOR_LEFT && ui->cur_x > 0) 660 return move_cursor(button, &ui->cur_x, &ui->cur_y, w-n+1, h-n+1,
662 ui->cur_x--; 661 false, &ui->cur_visible);
663 if (button == CURSOR_RIGHT && (ui->cur_x+n) < (w))
664 ui->cur_x++;
665 if (button == CURSOR_UP && ui->cur_y > 0)
666 ui->cur_y--;
667 if (button == CURSOR_DOWN && (ui->cur_y+n) < (h))
668 ui->cur_y++;
669 ui->cur_visible = true;
670 return UI_UPDATE;
671 }
672 662
673 if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { 663 if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
674 /* 664 /*
@@ -691,7 +681,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
691 dir = (button == CURSOR_SELECT2) ? -1 : +1; 681 dir = (button == CURSOR_SELECT2) ? -1 : +1;
692 } else { 682 } else {
693 ui->cur_visible = true; 683 ui->cur_visible = true;
694 return UI_UPDATE; 684 return MOVE_UI_UPDATE;
695 } 685 }
696 } else if (button == 'a' || button == 'A' || button==MOD_NUM_KEYPAD+'7') { 686 } else if (button == 'a' || button == 'A' || button==MOD_NUM_KEYPAD+'7') {
697 x = y = 0; 687 x = y = 0;
@@ -756,7 +746,7 @@ static game_state *execute_move(const game_state *from, const char *move)
756 * conveniently being able to get hold of a clean state from 746 * conveniently being able to get hold of a clean state from
757 * which to practise manoeuvres. 747 * which to practise manoeuvres.
758 */ 748 */
759 qsort(ret->grid, ret->w*ret->h, sizeof(int), compare_int); 749 qsort(ret->grid, ret->w*ret->h, sizeof(int), compare_integers);
760 for (i = 0; i < ret->w*ret->h; i++) 750 for (i = 0; i < ret->w*ret->h; i++)
761 ret->grid[i] &= ~3; 751 ret->grid[i] &= ~3;
762 ret->used_solve = true; 752 ret->used_solve = true;
@@ -791,7 +781,7 @@ static game_state *execute_move(const game_state *from, const char *move)
791 */ 781 */
792 782
793static void game_compute_size(const game_params *params, int tilesize, 783static void game_compute_size(const game_params *params, int tilesize,
794 int *x, int *y) 784 const game_ui *ui, int *x, int *y)
795{ 785{
796 /* Ick: fake up `ds->tilesize' for macro expansion purposes */ 786 /* Ick: fake up `ds->tilesize' for macro expansion purposes */
797 struct { int tilesize; } ads, *ds = &ads; 787 struct { int tilesize; } ads, *ds = &ads;
@@ -870,8 +860,8 @@ static void rotate(int *xy, struct rotation *rot)
870 xf2 = rot->c * xf + rot->s * yf; 860 xf2 = rot->c * xf + rot->s * yf;
871 yf2 = - rot->s * xf + rot->c * yf; 861 yf2 = - rot->s * xf + rot->c * yf;
872 862
873 xy[0] = (int)(xf2 + rot->ox + 0.5); /* round to nearest */ 863 xy[0] = (int)(xf2 + rot->ox + 0.5F); /* round to nearest */
874 xy[1] = (int)(yf2 + rot->oy + 0.5); /* round to nearest */ 864 xy[1] = (int)(yf2 + rot->oy + 0.5F); /* round to nearest */
875 } 865 }
876} 866}
877 867
@@ -1058,7 +1048,7 @@ static int highlight_colour(float angle)
1058 COL_LOWLIGHT, 1048 COL_LOWLIGHT,
1059 }; 1049 };
1060 1050
1061 return colours[(int)((angle + 2*PI) / (PI/16)) & 31]; 1051 return colours[(int)((angle + 2*(float)PI) / ((float)PI/16)) & 31];
1062} 1052}
1063 1053
1064static float game_anim_length_real(const game_state *oldstate, 1054static float game_anim_length_real(const game_state *oldstate,
@@ -1135,13 +1125,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
1135 if (!ds->started) { 1125 if (!ds->started) {
1136 int coords[10]; 1126 int coords[10];
1137 1127
1138 draw_rect(dr, 0, 0,
1139 TILE_SIZE * state->w + 2 * BORDER,
1140 TILE_SIZE * state->h + 2 * BORDER, COL_BACKGROUND);
1141 draw_update(dr, 0, 0,
1142 TILE_SIZE * state->w + 2 * BORDER,
1143 TILE_SIZE * state->h + 2 * BORDER);
1144
1145 /* 1128 /*
1146 * Recessed area containing the whole puzzle. 1129 * Recessed area containing the whole puzzle.
1147 */ 1130 */
@@ -1189,7 +1172,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
1189 rot->cw = rot->ch = TILE_SIZE * state->n; 1172 rot->cw = rot->ch = TILE_SIZE * state->n;
1190 rot->ox = rot->cx + rot->cw/2; 1173 rot->ox = rot->cx + rot->cw/2;
1191 rot->oy = rot->cy + rot->ch/2; 1174 rot->oy = rot->cy + rot->ch/2;
1192 angle = (float)((-PI/2 * lastr) * (1.0 - animtime / anim_max)); 1175 angle = ((-(float)PI/2 * lastr) * (1.0F - animtime / anim_max));
1193 rot->c = (float)cos(angle); 1176 rot->c = (float)cos(angle);
1194 rot->s = (float)sin(angle); 1177 rot->s = (float)sin(angle);
1195 1178
@@ -1282,19 +1265,6 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
1282 } 1265 }
1283} 1266}
1284 1267
1285static bool game_timing_state(const game_state *state, game_ui *ui)
1286{
1287 return true;
1288}
1289
1290static void game_print_size(const game_params *params, float *x, float *y)
1291{
1292}
1293
1294static void game_print(drawing *dr, const game_state *state, int tilesize)
1295{
1296}
1297
1298#ifdef COMBINED 1268#ifdef COMBINED
1299#define thegame twiddle 1269#define thegame twiddle
1300#endif 1270#endif
@@ -1316,12 +1286,14 @@ const struct game thegame = {
1316 free_game, 1286 free_game,
1317 true, solve_game, 1287 true, solve_game,
1318 true, game_can_format_as_text_now, game_text_format, 1288 true, game_can_format_as_text_now, game_text_format,
1289 NULL, NULL, /* get_prefs, set_prefs */
1319 new_ui, 1290 new_ui,
1320 free_ui, 1291 free_ui,
1321 encode_ui, 1292 NULL, /* encode_ui */
1322 decode_ui, 1293 NULL, /* decode_ui */
1323 NULL, /* game_request_keys */ 1294 NULL, /* game_request_keys */
1324 game_changed_state, 1295 game_changed_state,
1296 current_key_label,
1325 interpret_move, 1297 interpret_move,
1326 execute_move, 1298 execute_move,
1327 PREFERRED_TILE_SIZE, game_compute_size, game_set_size, 1299 PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
@@ -1333,9 +1305,9 @@ const struct game thegame = {
1333 game_flash_length, 1305 game_flash_length,
1334 game_get_cursor_location, 1306 game_get_cursor_location,
1335 game_status, 1307 game_status,
1336 false, false, game_print_size, game_print, 1308 false, false, NULL, NULL, /* print_size, print */
1337 true, /* wants_statusbar */ 1309 true, /* wants_statusbar */
1338 false, game_timing_state, 1310 false, NULL, /* timing_state */
1339 0, /* flags */ 1311 0, /* flags */
1340}; 1312};
1341 1313