Mouse-based interface for Cube: you left-click anywhere on the grid
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 31 May 2005 11:43:51 +0000 (11:43 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 31 May 2005 11:43:51 +0000 (11:43 +0000)
and it moves the polyhedron in the general direction of the mouse
pointer. (I had this in my initial throwaway Python implementation
of this game, but never reimplemented it in this version. It's
harder with triangles, but not too much harder.)

Since the logical-to-physical coordinate mapping in Cube is
dynamically computed, this has involved an interface change which
touches all puzzles: make_move() is now passed a pointer to the
game_drawstate, which it may of course completely ignore if it
wishes.

git-svn-id: svn://svn.tartarus.org/sgt/puzzles@5877 cda61777-01e9-0310-a592-d414129be87e

13 files changed:
cube.c
fifteen.c
midend.c
mines.c
net.c
netslide.c
nullgame.c
pattern.c
puzzles.h
rect.c
sixteen.c
solo.c
twiddle.c

diff --git a/cube.c b/cube.c
index 2bce1bd..bf24960 100644 (file)
--- a/cube.c
+++ b/cube.c
@@ -11,6 +11,8 @@
 
 #include "puzzles.h"
 
+#define PI 3.14159265358979323846264338327950884197169399
+
 #define MAXVERTICES 20
 #define MAXFACES 20
 #define MAXORDER 4
@@ -1002,7 +1004,11 @@ static void free_ui(game_ui *ui)
 {
 }
 
-static game_state *make_move(game_state *from, game_ui *ui,
+struct game_drawstate {
+    int ox, oy;                        /* pixel position of float origin */
+};
+
+static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
                             int x, int y, int button)
 {
     int direction;
@@ -1016,7 +1022,9 @@ static game_state *make_move(game_state *from, game_ui *ui,
     button = button & (~MOD_MASK | MOD_NUM_KEYPAD);
 
     /*
-     * All moves are made with the cursor keys or numeric keypad.
+     * Moves can be made with the cursor keys or numeric keypad, or
+     * alternatively you can left-click and the polyhedron will
+     * move in the general direction of the mouse pointer.
      */
     if (button == CURSOR_UP || button == (MOD_NUM_KEYPAD | '8'))
         direction = UP;
@@ -1034,7 +1042,69 @@ static game_state *make_move(game_state *from, game_ui *ui,
         direction = UP_RIGHT;
     else if (button == (MOD_NUM_KEYPAD | '3'))
         direction = DOWN_RIGHT;
-    else
+    else if (button == LEFT_BUTTON) {
+        /*
+         * Find the bearing of the click point from the current
+         * square's centre.
+         */
+        int cx, cy;
+        double angle;
+
+        cx = from->squares[from->current].x * GRID_SCALE + ds->ox;
+        cy = from->squares[from->current].y * GRID_SCALE + ds->oy;
+
+        if (x == cx && y == cy)
+            return NULL;               /* clicked in exact centre!  */
+        angle = atan2(y - cy, x - cx);
+
+        /*
+         * There are three possibilities.
+         * 
+         *  - This square is a square, so we choose between UP,
+         *    DOWN, LEFT and RIGHT by dividing the available angle
+         *    at the 45-degree points.
+         * 
+         *  - This square is an up-pointing triangle, so we choose
+         *    between DOWN, LEFT and RIGHT by dividing into
+         *    120-degree arcs.
+         * 
+         *  - This square is a down-pointing triangle, so we choose
+         *    between UP, LEFT and RIGHT in the inverse manner.
+         * 
+         * Don't forget that since our y-coordinates increase
+         * downwards, `angle' is measured _clockwise_ from the
+         * x-axis, not anticlockwise as most mathematicians would
+         * instinctively assume.
+         */
+        if (from->squares[from->current].npoints == 4) {
+            /* Square. */
+            if (fabs(angle) > 3*PI/4)
+                direction = LEFT;
+            else if (fabs(angle) < PI/4)
+                direction = RIGHT;
+            else if (angle > 0)
+                direction = DOWN;
+            else
+                direction = UP;
+        } else if (from->squares[from->current].directions[UP] == 0) {
+            /* Up-pointing triangle. */
+            if (angle < -PI/2 || angle > 5*PI/6)
+                direction = LEFT;
+            else if (angle > PI/6)
+                direction = DOWN;
+            else
+                direction = RIGHT;
+        } else {
+            /* Down-pointing triangle. */
+            assert(from->squares[from->current].directions[DOWN] == 0);
+            if (angle > PI/2 || angle < -5*PI/6)
+                direction = LEFT;
+            else if (angle < -PI/6)
+                direction = UP;
+            else
+                direction = RIGHT;
+        }
+    } else
         return NULL;
 
     /*
@@ -1288,10 +1358,6 @@ struct bbox {
     float l, r, u, d;
 };
 
-struct game_drawstate {
-    int ox, oy;                        /* pixel position of float origin */
-};
-
 static void find_bbox_callback(void *ctx, struct grid_square *sq)
 {
     struct bbox *bb = (struct bbox *)ctx;
index e7a41ef..49a3118 100644 (file)
--- a/fifteen.c
+++ b/fifteen.c
@@ -450,9 +450,8 @@ static void free_ui(game_ui *ui)
 {
 }
 
-static game_state *make_move(game_state *from, game_ui *ui,
-                            int x, int y, int button)
-{
+static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
+                             int x, int y, int button) {
     int gx, gy, dx, dy, ux, uy, up, p;
     game_state *ret;
 
index de20e14..1def041 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -325,7 +325,7 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button)
     } else {
         game_state *s =
             me->ourgame->make_move(me->states[me->statepos-1].state,
-                                   me->ui, x, y, button);
+                                   me->ui, me->drawstate, x, y, button);
 
         if (s == me->states[me->statepos-1].state) {
             /*
diff --git a/mines.c b/mines.c
index 10ca76c..4006294 100644 (file)
--- a/mines.c
+++ b/mines.c
@@ -2229,8 +2229,8 @@ static void free_ui(game_ui *ui)
     sfree(ui);
 }
 
-static game_state *make_move(game_state *from, game_ui *ui, int x, int y,
-                            int button)
+static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
+                             int x, int y, int button)
 {
     game_state *ret;
     int cx, cy;
diff --git a/net.c b/net.c
index a2204c0..447f4e3 100644 (file)
--- a/net.c
+++ b/net.c
@@ -1798,8 +1798,7 @@ static void free_ui(game_ui *ui)
  * Process a move.
  */
 static game_state *make_move(game_state *state, game_ui *ui,
-                            int x, int y, int button)
-{
+                             game_drawstate *ds, int x, int y, int button) {
     game_state *ret, *nullret;
     int tx, ty, orig;
     int shift = button & MOD_SHFT, ctrl = button & MOD_CTRL;
index 324946e..b81a816 100644 (file)
@@ -1051,7 +1051,7 @@ static void slide_col(game_state *state, int dir, int col)
 }
 
 static game_state *make_move(game_state *state, game_ui *ui,
-                            int x, int y, int button)
+                             game_drawstate *ds, int x, int y, int button)
 {
     int cx, cy;
     int n, dx, dy;
index 3ec6b75..56694de 100644 (file)
@@ -142,8 +142,8 @@ static void free_ui(game_ui *ui)
 {
 }
 
-static game_state *make_move(game_state *from, game_ui *ui, int x, int y,
-                            int button)
+static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
+                             int x, int y, int button)
 {
     return NULL;
 }
index 419e4aa..4cd3669 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -764,9 +764,8 @@ static void free_ui(game_ui *ui)
     sfree(ui);
 }
 
-static game_state *make_move(game_state *from, game_ui *ui,
-                            int x, int y, int button)
-{
+static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
+                             int x, int y, int button) {
     game_state *ret;
 
     button &= ~MOD_MASK;
index bf441c6..de0f819 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -227,8 +227,8 @@ struct game {
     char *(*text_format)(game_state *state);
     game_ui *(*new_ui)(game_state *state);
     void (*free_ui)(game_ui *ui);
-    game_state *(*make_move)(game_state *from, game_ui *ui, int x, int y,
-                            int button);
+    game_state *(*make_move)(game_state *from, game_ui *ui, game_drawstate *ds,
+                             int x, int y, int button);
     void (*size)(game_params *params, int *x, int *y);
     float *(*colours)(frontend *fe, game_state *state, int *ncolours);
     game_drawstate *(*new_drawstate)(game_state *state);
diff --git a/rect.c b/rect.c
index c1eaa2c..9e4204d 100644 (file)
--- a/rect.c
+++ b/rect.c
@@ -2178,9 +2178,8 @@ static void ui_draw_rect(game_state *state, game_ui *ui,
             }
 }
 
-static game_state *make_move(game_state *from, game_ui *ui,
-                            int x, int y, int button)
-{
+static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
+                             int x, int y, int button) {
     int xc, yc;
     int startdrag = FALSE, enddrag = FALSE, active = FALSE;
     game_state *ret;
index c6664c1..c202de1 100644 (file)
--- a/sixteen.c
+++ b/sixteen.c
@@ -577,9 +577,8 @@ static void free_ui(game_ui *ui)
 {
 }
 
-static game_state *make_move(game_state *from, game_ui *ui,
-                            int x, int y, int button)
-{
+static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
+                             int x, int y, int button) {
     int cx, cy;
     int dx, dy, tx, ty, n;
     game_state *ret;
diff --git a/solo.c b/solo.c
index 168551c..f3afb02 100644 (file)
--- a/solo.c
+++ b/solo.c
@@ -1821,8 +1821,8 @@ static void free_ui(game_ui *ui)
     sfree(ui);
 }
 
-static game_state *make_move(game_state *from, game_ui *ui, int x, int y,
-                            int button)
+static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
+                             int x, int y, int button)
 {
     int c = from->c, r = from->r, cr = c*r;
     int tx, ty;
index f7bfd4a..273ce8c 100644 (file)
--- a/twiddle.c
+++ b/twiddle.c
@@ -618,8 +618,8 @@ static void free_ui(game_ui *ui)
 {
 }
 
-static game_state *make_move(game_state *from, game_ui *ui, int x, int y,
-                            int button)
+static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
+                             int x, int y, int button)
 {
     int w = from->w, h = from->h, n = from->n, wh = w*h;
     game_state *ret;