General further development. Sketched out the mid-end, added more
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 25 Apr 2004 20:15:22 +0000 (20:15 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 25 Apr 2004 20:15:22 +0000 (20:15 +0000)
GTK code, rudiments of event passing.

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

gtk.c
midend.c
net.c
puzzles.h

diff --git a/gtk.c b/gtk.c
index 1d5ffdc..8bb01fd 100644 (file)
--- a/gtk.c
+++ b/gtk.c
@@ -41,6 +41,8 @@ void fatal(char *fmt, ...)
  */
 struct window_data {
     GtkWidget *window;
+    GtkWidget *area;
+    midend_data *me;
 };
 
 static void destroy(GtkWidget *widget, gpointer data)
@@ -48,15 +50,52 @@ static void destroy(GtkWidget *widget, gpointer data)
     gtk_main_quit();
 }
 
+gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+    struct window_data *wdata = (struct window_data *)data;
+
+    IGNORE(wdata);
+
+    if (!midend_process_key(wdata->me, 0, 0, event->keyval))
+       gtk_widget_destroy(wdata->window);
+
+    return TRUE;
+}
+
+gint button_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+    struct window_data *wdata = (struct window_data *)data;
+
+    IGNORE(wdata);
+
+    return TRUE;
+}
+
 static struct window_data *new_window(void)
 {
     struct window_data *wdata;
+    int x, y;
 
     wdata = snew(struct window_data);
 
+    wdata->me = midend_new();
+    midend_new_game(wdata->me, NULL);
+
     wdata->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+    wdata->area = gtk_drawing_area_new();
+    midend_size(wdata->me, &x, &y);
+    gtk_drawing_area_size(GTK_DRAWING_AREA(wdata->area), x, y);
+
+    gtk_container_add(GTK_CONTAINER(wdata->window), wdata->area);
+    gtk_widget_show(wdata->area);
+
     gtk_signal_connect(GTK_OBJECT(wdata->window), "destroy",
                       GTK_SIGNAL_FUNC(destroy), wdata);
+    gtk_signal_connect(GTK_OBJECT(wdata->window), "key_press_event",
+                      GTK_SIGNAL_FUNC(key_event), wdata);
+    gtk_signal_connect(GTK_OBJECT(wdata->area), "button_press_event",
+                      GTK_SIGNAL_FUNC(button_event), wdata);
     gtk_widget_show(wdata->window);
     return wdata;
 }
index 2adbf9f..9d05b44 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -4,3 +4,124 @@
  * Maintains a move list, takes care of Undo and Redo commands, and
  * processes standard keystrokes for undo/redo/new/restart/quit.
  */
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "puzzles.h"
+
+struct midend_data {
+    char *seed;
+    int nstates, statesize, statepos;
+    game_params *params;
+    game_state **states;
+};
+
+#define ensure(me) do { \
+    if ((me)->nstates >= (me)->statesize) { \
+       (me)->statesize = (me)->nstates + 128; \
+       (me)->states = sresize((me)->states, (me)->statesize, game_state *); \
+    } \
+} while (0)
+
+midend_data *midend_new(void)
+{
+    midend_data *me = snew(midend_data);
+
+    me->nstates = me->statesize = me->statepos = 0;
+    me->states = NULL;
+    me->params = default_params();
+    me->seed = NULL;
+
+    return me;
+}
+
+void midend_free(midend_data *me)
+{
+    sfree(me->states);
+    sfree(me->seed);
+    free_params(me->params);
+    sfree(me);
+}
+
+void midend_size(midend_data *me, int *x, int *y)
+{
+    game_size(me->params, x, y);
+}
+
+void midend_set_params(midend_data *me, game_params *params)
+{
+    free_params(me->params);
+    me->params = params;
+}
+
+void midend_new_game(midend_data *me, char *seed)
+{
+    while (me->nstates > 0)
+       free_game(me->states[--me->nstates]);
+
+    assert(me->nstates == 0);
+
+    sfree(me->seed);
+    if (seed)
+       me->seed = dupstr(seed);
+    else
+       me->seed = new_game_seed(me->params);
+
+    ensure(me);
+    me->states[me->nstates++] = new_game(me->params, me->seed);
+    me->statepos = 1;
+}
+
+void midend_restart_game(midend_data *me)
+{
+    while (me->nstates > 1)
+       free_game(me->states[--me->nstates]);
+    me->statepos = me->nstates;
+}
+
+void midend_undo(midend_data *me)
+{
+    if (me->statepos > 1)
+       me->statepos--;
+}
+
+void midend_redo(midend_data *me)
+{
+    if (me->statepos < me->nstates)
+       me->statepos++;
+}
+
+int midend_process_key(midend_data *me, int x, int y, int button)
+{
+    game_state *s;
+
+    if (button == 'n' || button == 'N' || button == '\x0E') {
+       midend_new_game(me, NULL);
+       return 1;
+    } else if (button == 'r' || button == 'R') {
+       midend_restart_game(me);
+       return 1;
+    } else if (button == 'u' || button == 'u' ||
+              button == '\x1A' || button == '\x1F') {
+       midend_undo(me);
+       return 1;
+    } else if (button == '\x12') {
+       midend_redo(me);
+       return 1;
+    } else if (button == 'q' || button == 'Q' || button == '\x11') {
+       return 0;
+    }
+
+    s = make_move(me->states[me->statepos-1], x, y, button);
+
+    if (s) {
+       while (me->nstates > me->statepos)
+           free_game(me->states[--me->nstates]);
+       ensure(me);
+       me->states[me->nstates] = s;
+       me->statepos = ++me->nstates;
+    }
+
+    return 1;
+}
diff --git a/net.c b/net.c
index a5fe8c0..2196807 100644 (file)
--- a/net.c
+++ b/net.c
@@ -90,6 +90,26 @@ static struct xyd *new_xyd(int x, int y, int direction)
 }
 
 /* ----------------------------------------------------------------------
+ * Manage game parameters.
+ */
+game_params *default_params(void)
+{
+    game_params *ret = snew(game_params);
+
+    ret->width = 5;
+    ret->height = 5;
+    ret->wrapping = FALSE;
+    ret->barrier_probability = 0.0;
+
+    return ret;
+}
+
+void free_params(game_params *params)
+{
+    sfree(params);
+}
+
+/* ----------------------------------------------------------------------
  * Randomly select a new game seed.
  */
 
@@ -511,8 +531,8 @@ game_state *make_move(game_state *state, int x, int y, int button)
     /*
      * The button must have been clicked on a valid tile.
      */
-    x -= WINDOW_OFFSET;
-    y -= WINDOW_OFFSET;
+    x -= WINDOW_OFFSET + TILE_BORDER;
+    y -= WINDOW_OFFSET + TILE_BORDER;
     if (x < 0 || y < 0)
        return NULL;
     tx = x / TILE_SIZE;
@@ -586,6 +606,12 @@ game_state *make_move(game_state *state, int x, int y, int button)
  * Routines for drawing the game position on the screen.
  */
 
+void game_size(game_params *params, int *x, int *y)
+{
+    *x = WINDOW_OFFSET * 2 + TILE_SIZE * params->width + TILE_BORDER;
+    *y = WINDOW_OFFSET * 2 + TILE_SIZE * params->height + TILE_BORDER;
+}
+
 /* ----------------------------------------------------------------------
  * Test code.
  */
index ca961a6..06e9624 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -20,12 +20,32 @@ enum {
     RIGHT_BUTTON
 };
 
+#define IGNORE(x) ( (x) = (x) )
+
+typedef struct midend_data midend_data;
+typedef struct random_state random_state;
+typedef struct game_params game_params;
+typedef struct game_state game_state;
+
 /*
  * Platform routines
  */
 void fatal(char *fmt, ...);
 
 /*
+ * midend.c
+ */
+midend_data *midend_new(void);
+void midend_free(midend_data *me);
+void midend_set_params(midend_data *me, game_params *params);
+void midend_size(midend_data *me, int *x, int *y);
+void midend_new_game(midend_data *me, char *seed);
+void midend_restart_game(midend_data *me);
+void midend_undo(midend_data *me);
+void midend_redo(midend_data *me);
+int midend_process_key(midend_data *me, int x, int y, int button);
+
+/*
  * malloc.c
  */
 void *smalloc(int size);
@@ -37,12 +57,11 @@ char *dupstr(char *s);
 #define snewn(number, type) \
     ( (type *) smalloc ((number) * sizeof (type)) )
 #define sresize(array, number, type) \
-    ( (type *) srealloc ((array), (len) * sizeof (type)) )
+    ( (type *) srealloc ((array), (number) * sizeof (type)) )
 
 /*
  * random.c
  */
-typedef struct random_state random_state;
 random_state *random_init(char *seed, int len);
 unsigned long random_upto(random_state *state, unsigned long limit);
 void random_free(random_state *state);
@@ -50,12 +69,13 @@ void random_free(random_state *state);
 /*
  * Game-specific routines
  */
-typedef struct game_params game_params;
-typedef struct game_state game_state;
+game_params *default_params(void);
+void free_params(game_params *params);
 char *new_game_seed(game_params *params);
 game_state *new_game(game_params *params, char *seed);
 game_state *dup_game(game_state *state);
 void free_game(game_state *state);
 game_state *make_move(game_state *from, int x, int y, int button);
+void game_size(game_params *params, int *x, int *y);
 
 #endif /* PUZZLES_PUZZLES_H */