From: simon Date: Sun, 25 Apr 2004 20:15:22 +0000 (+0000) Subject: General further development. Sketched out the mid-end, added more X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/commitdiff_plain/7f77ea2439f0c82e537fb0f7dbd4bb7c08bf851a General further development. Sketched out the mid-end, added more GTK code, rudiments of event passing. git-svn-id: svn://svn.tartarus.org/sgt/puzzles@4141 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/gtk.c b/gtk.c index 1d5ffdc..8bb01fd 100644 --- 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; } diff --git a/midend.c b/midend.c index 2adbf9f..9d05b44 100644 --- 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 +#include + +#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 --- 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. */ diff --git a/puzzles.h b/puzzles.h index ca961a6..06e9624 100644 --- 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 */