+2003-06-19 Carl Worth <cworth@isi.edu>
+
+ * src/grrobot.c (grr_game_print): Centralized game message
+ printing.
+ (grr_game_read_notices): New formatted messages for all notice
+ types.
+ (grr_game_read_notices): Fancy incremental updates for move
+ messages.
+ (grr_game_print): Fixed (finally) scrolling of messages.
+
dnl ===========================================================================
-AM_INIT_AUTOMAKE(xsvg, $GRROBOT_VERSION)
+AM_INIT_AUTOMAKE(grrobot, $GRROBOT_VERSION)
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
AC_OUTPUT([
Makefile
src/Makefile
+src/svg/Makefile
])
+SUBDIRS = . svg
+
bin_PROGRAMS = grrobot
grrobot_SOURCES = \
args.h \
grrobot.c \
grr_board_view.c \
- grr_board_view.h
+ grr_board_view.h \
+ grr_util.c \
+ grr_util.h
-INCLUDES = $(GRROBOT_CFLAGS)
+INCLUDES = $(GRROBOT_CFLAGS) -DGRR_ICON_DIR=\"$(pkgdatadir)\"
LDFLAGS = $(GRROBOT_LIBS)
-
-
-
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdarg.h>
#include <Xr.h>
#include <xsvg.h>
#include <gdk/gdkx.h>
#include "grr_board_view.h"
+#include "grr_util.h"
#define SCROLL_DELAY_LENGTH 300
#define GRR_BOARD_VIEW_DEFAULT_SIZE 100
/* Forward declarations */
-static int
-grr_sprintf_alloc (char **str, const char *fmt, ...);
-
-static int
-grr_sprintf_alloc_va (char **str, const char *fmt, va_list ap);
-
-
static void grr_board_view_class_init (grr_board_view_class_t *klass);
static void grr_board_view_init (grr_board_view_t *view);
static void grr_board_view_destroy (GtkObject *object);
gtk_widget_queue_draw (GTK_WIDGET (view));
}
-static int
-grr_sprintf_alloc (char **str, const char *fmt, ...)
-{
- int ret;
- va_list ap;
-
- va_start(ap, fmt);
- ret = grr_sprintf_alloc_va (str, fmt, ap);
- va_end(ap);
-
- return ret;
-}
-
-/* ripped more or less straight out of PRINTF(3) */
-static int
-grr_sprintf_alloc_va (char **str, const char *fmt, va_list ap)
-{
- char *new_str;
- /* Guess we need no more than 100 bytes. */
- int n, size = 100;
-
- if ((*str = malloc (size)) == NULL)
- return -1;
- while (1) {
- /* Try to print in the allocated space. */
- n = vsnprintf (*str, size, fmt, ap);
- /* If that worked, return the size. */
- if (n > -1 && n < size)
- return n;
- /* Else try again with more space. */
- if (n > -1) /* glibc 2.1 */
- size = n+1; /* precisely what is needed */
- else /* glibc 2.0 */
- size *= 2; /* twice the old size */
- new_str = realloc(*str, size);
- if (new_str == NULL) {
- free(*str);
- *str = NULL;
- return -1;
- }
- *str = new_str;
- }
-}
--- /dev/null
+/* grrobot - Ricochet Robot using GTK+ and Xr
+ *
+ * Copyright © 2003 Carl Worth
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Carl Worth
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * Carl Worth makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * CARL WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL CARL WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl Worth <carl@theworths.org>
+ */
+
+#include "grr_icon.h"
+#include "grr_icon_svg.h"
+
+struct {
+ int type;
+ char *name;
+ char *svg;
+} icons[] = {
+ { RR_ROBOT_BLUE,
+ "robot_blue", GRR_ICON_SVG_ROBOT_BLUE },
+ { RR_ROBOT_GREEN,
+ "robot_green", GRR_ICON_SVG_ROBOT_GREEN },
+ { RR_ROBOT_RED,
+ "robot_red", GRR_ICON_SVG_ROBOT_RED },
+ { RR_ROBOT_YELLOW,
+ "robot_yellow", GRR_ICON_SVG_ROBOT_YELLOW },
+
+ { RR_TARGET_BLUE_CIRCLE,
+ "target_blue_circle", GRR_ICON_SVG_TARGET_BLUE_CIRCLE },
+ { RR_TARGET_BLUE_OCTAGON,
+ "target_blue_octagon", GRR_ICON_SVG_TARGET_BLUE_OCTAGON },
+ { RR_TARGET_BLUE_SQUARE,
+ "target_blue_square", GRR_ICON_SVG_TARGET_BLUE_SQUARE },
+ { RR_TARGET_BLUE_TRIANGLE,
+ "target_blue_triangle", GRR_ICON_SVG_TARGET_BLUE_TRIANGLE },
+
+ { RR_TARGET_GREEN_CIRCLE,
+ "target_green_circle", GRR_ICON_SVG_TARGET_GREEN_CIRCLE },
+ { RR_TARGET_GREEN_OCTAGON,
+ "target_green_octagon", GRR_ICON_SVG_TARGET_GREEN_OCTAGON },
+ { RR_TARGET_GREEN_SQUARE,
+ "target_green_square", GRR_ICON_SVG_TARGET_GREEN_SQUARE },
+ { RR_TARGET_GREEN_TRIANGLE,
+ "target_green_triangle", GRR_ICON_SVG_TARGET_GREEN_TRIANGLE },
+
+ { RR_TARGET_RED_CIRCLE,
+ "target_red_circle", GRR_ICON_SVG_TARGET_RED_CIRCLE },
+ { RR_TARGET_RED_OCTAGON,
+ "target_red_octagon", GRR_ICON_SVG_TARGET_RED_OCTAGON },
+ { RR_TARGET_RED_SQUARE,
+ "target_red_square", GRR_ICON_SVG_TARGET_RED_SQUARE },
+ { RR_TARGET_RED_TRIANGLE,
+ "target_red_triangle", GRR_ICON_SVG_TARGET_RED_TRIANGLE },
+
+ { RR_TARGET_YELLOW_CIRCLE,
+ "target_yellow_circle", GRR_ICON_SVG_TARGET_YELLOW_CIRCLE },
+ { RR_TARGET_YELLOW_OCTAGON,
+ "target_yellow_octagon", GRR_ICON_SVG_TARGET_YELLOW_OCTAGON },
+ { RR_TARGET_YELLOW_SQUARE,
+ "target_yellow_square", GRR_ICON_SVG_TARGET_YELLOW_SQUARE },
+ { RR_TARGET_YELLOW_TRIANGLE,
+ "target_yellow_triangle", GRR_ICON_SVG_TARGET_YELLOW_TRIANGLE },
+
+ { RR_TARGET_WHIRL,
+ "whirl", GRR_ICON_SVG_TARGET_WHIRL },
+
+ { RR_WALL_ABOVE,
+ "wall", GRR_ICON_SVG_WALL },
+
+ { RR_CELL,
+ "cell", GRR_ICON_SVG_CELL }
+};
+
+typedef struct grr_icon {
+ xsvg_t *xsvg;
+} grr_icon_t;
+
+grr_icon_t *
+grr_icon_create (char *name)
+{
+ grr_icon *icon;
+
+ icon = malloc (sizeof (grr_icon_t));
+ if (icon == NULL)
+ return NULL;
+
+ _grr_icon_init (icon, name);
+
+ return icon;
+}
+
+static rr_status_t
+_grr_icon_init (grr_icon_t *icon, char *name)
+{
+ xsvg_status_t status;
+ char *file, *buf;
+
+ status = xsvg_create (&icon->xsvg);
+ if (status)
+ return RR_STATUS_NO_MEMORY;
+
+ file = grr_icon_find_file (name);
+
+ if (file) {
+ status = xsvg_parse_file (icon->xsvg, file);
+ if (status == XSVG_STATUS_SUCCESS) {
+ free (file);
+ return RR_STATUS_SUCCESS;
+ }
+ fprintf (stderr, "Error parsing SVG icon: %s\n", file);
+ free (file);
+ }
+
+ buf = grr_icon_find_buffer (name);
+ status = xsvg_parse_buffer (icon->xsvg, buf, strlen (buf));
+ if (status) {
+ fprintf (stderr, "Error parsing built-in SVG icon for: %s\n", name);
+ return RR_STATUS_PARSE_ERROR;
+ }
+
+ return RR_STATUS_SUCCESS;
+}
+
+/* XXX: This could be made more interesting, (eg. search in ~/.grrobot
+ or something). */
+static char *
+_grr_icon_find_file (char *name)
+{
+ int err;
+ char *file;
+ struct stat stat_buf;
+
+ rr_string_sprintf_alloc (&file, "%s/%s", GRR_ICON_DIR, name);
+ if (file == NULL)
+ return NULL;
+
+ err = stat (file, &stat_buf);
+ if (err == 0 && S_ISREG (state.st_mode))
+ return (file);
+ free (file);
+}
--- /dev/null
+/* grrobot - Ricochet Robot using GTK+ and Xr
+ *
+ * Copyright © 2003 Carl Worth
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Carl Worth
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * Carl Worth makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * CARL WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL CARL WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl Worth <carl@theworths.org>
+ */
+
+#ifndef GRR_ICON_H
+#define GRR_ICON_H
+
+typedef struct grr_icon {
+ xsvg_t *xsvg;
+} grr_icon_t;
+
+grr_icon_t *
+grr_icon_create (char *name)
+{
+ grr_icon *icon;
+
+ icon = malloc (sizeof (grr_icon_t));
+ if (icon == NULL)
+ return NULL;
+
+ _grr_icon_init (icon, name);
+
+ return icon;
+}
+
+static rr_status_t
+_grr_icon_init (grr_icon_t *icon, char *name)
+{
+ xsvg_status_t status;
+ char *file, *buf;
+
+ status = xsvg_create (&icon->xsvg);
+ if (status)
+ return RR_STATUS_NO_MEMORY;
+
+ file = grr_icon_find_file (name);
+
+ if (file) {
+ status = xsvg_parse_file (icon->xsvg, file);
+ if (status == XSVG_STATUS_SUCCESS) {
+ free (file);
+ return RR_STATUS_SUCCESS;
+ }
+ fprintf (stderr, "Error parsing SVG icon: %s\n", file);
+ free (file);
+ }
+
+ buf = grr_icon_find_buffer (name);
+ status = xsvg_parse_buffer (icon->xsvg, buf, strlen (buf));
+ if (status) {
+ fprintf (stderr, "Error parsing built-in SVG icon for: %s\n", name);
+ return RR_STATUS_PARSE_ERROR;
+ }
+
+ return RR_STATUS_SUCCESS;
+}
+
+/* XXX: This could be made more interesting, (eg. search in ~/.grrobot
+ or something). */
+static char *
+_grr_icon_find_file (char *name)
+{
+ int err;
+ char *file;
+ struct stat stat_buf;
+
+ rr_string_sprintf_alloc (&file, "%s/%s", GRR_ICON_DIR, name);
+ if (file == NULL)
+ return NULL;
+
+ err = stat (file, &stat_buf);
+ if (err == 0 && S_ISREG (state.st_mode))
+ return (file);
+ free (file);
+}
+
+extern char *GRR_ROBOT_BLUE_SVG;
+extern char *GRR_ROBOT_GREEN_SVG;
+extern char *GRR_ROBOT_RED_SVG;
+extern char *GRR_ROBOT_YELLOW_SVG;
+
+extern char *GRR_TARGET_BLUE_CIRCLE_SVG;
+extern char *GRR_TARGET_GREEN_CIRCLE_SVG;
+extern char *GRR_TARGET_RED_CIRCLE_SVG;
+extern char *GRR_TARGET_YELLOW_CIRCLE_SVG;
+
+extern char *GRR_TARGET_BLUE_OCTAGON_SVG;
+extern char *GRR_TARGET_GREEN_OCTAGON_SVG;
+extern char *GRR_TARGET_RED_OCTAGON_SVG;
+extern char *GRR_TARGET_YELLOW_OCTAGON_SVG;
+
+extern char *GRR_TARGET_BLUE_SQUARE_SVG;
+extern char *GRR_TARGET_GREEN_SQUARE_SVG;
+extern char *GRR_TARGET_RED_SQUARE_SVG;
+extern char *GRR_TARGET_YELLOW_SQUARE_SVG;
+
+extern char *GRR_TARGET_BLUE_TRIANGLE_SVG;
+extern char *GRR_TARGET_GREEN_TRIANGLE_SVG;
+extern char *GRR_TARGET_RED_TRIANGLE_SVG;
+extern char *GRR_TARGET_YELLOW_TRIANGLE_SVG;
+
+extern char *GRR_TARGET_WHIRL_SVG;
+
+#endif
--- /dev/null
+/* grr_board_view - GTK+ widget for displaying an rr_board
+ *
+ * Copyright © 2003 Carl Worth
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Carl Worth
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * Carl Worth makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * CARL WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL CARL WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl Worth <carl@theworths.org>
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "grr_util.h"
+
+int
+grr_sprintf_alloc (char **str, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start (ap, fmt);
+ ret = grr_sprintf_alloc_va (str, fmt, ap);
+ va_end (ap);
+
+ return ret;
+}
+
+/* ripped more or less straight out of PRINTF(3) */
+int
+grr_sprintf_alloc_va (char **str, const char *fmt, va_list ap)
+{
+ char *new_str;
+ /* Guess we need no more than 100 bytes. */
+ int n, size = 100;
+
+ if ((*str = malloc (size)) == NULL)
+ return -1;
+ while (1) {
+ /* Try to print in the allocated space. */
+ n = vsnprintf (*str, size, fmt, ap);
+ /* If that worked, return the size. */
+ if (n > -1 && n < size)
+ return n;
+ /* Else try again with more space. */
+ if (n > -1) /* glibc 2.1 */
+ size = n+1; /* precisely what is needed */
+ else /* glibc 2.0 */
+ size *= 2; /* twice the old size */
+ new_str = realloc(*str, size);
+ if (new_str == NULL) {
+ free(*str);
+ *str = NULL;
+ return -1;
+ }
+ *str = new_str;
+ }
+}
+
+
--- /dev/null
+/* grr_board_view - GTK+ widget for displaying an rr_board
+ *
+ * Copyright © 2003 Carl Worth
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Carl Worth
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * Carl Worth makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * CARL WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL CARL WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl Worth <carl@theworths.org>
+ */
+
+#ifndef GRR_UTIL_H
+#define GRR_UTIL_H
+
+#include <stdarg.h>
+#include <stdio.h>
+
+int
+grr_sprintf_alloc (char **str, const char *fmt, ...);
+
+int
+grr_sprintf_alloc_va (char **str, const char *fmt, va_list ap);
+
+#endif
+
+
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+
#include <gtk/gtk.h>
#include "grr_board_view.h"
+#include "grr_util.h"
#include "args.h"
typedef struct grr_game {
GtkWidget *window;
GtkWidget *board_view;
+ GtkWidget *command_entry;
+
GtkTextBuffer *message_buffer;
GtkWidget *message_view;
- GtkWidget *command_entry;
- GtkTextIter message_iter;
+ int msg_id;
+ int last_move_msg_id;
+ rr_robot_t last_move_robot;
} grr_game_t;
+static int
+grr_game_printf (grr_game_t *game, const char *fmt, ...);
+
+static int
+grr_game_vprintf (grr_game_t *game, const char *fmt, va_list ap);
+
+static int
+grr_game_print (grr_game_t *game, const char *msg);
+
static int
grr_game_start_gui (grr_game_t *game);
}
game.board = rr_board_create (16, 16);
+ game.msg_id = 0;
+ game.last_move_msg_id = 0;
+ game.last_move_robot = RR_ROBOT_NONE;
source = grr_game_notices_source_new (&game);
g_source_set_priority (source, GDK_PRIORITY_EVENTS);
{
rr_board_t *board = game->board;
rr_status_t status;
- char **notice_s;
rr_notice_t *notice;
- int i;
while (rr_client_notice_pending (game->client)) {
- status = rr_client_next_notice (game->client, ¬ice_s);
+ status = rr_client_next_notice (game->client, ¬ice);
if (status) {
- fprintf (stderr, "Error during rr_client_notice: %s\n",
+ fprintf (stderr, "Error during rr_client_next_notice: %s\n",
rr_status_str (status));
gtk_exit (1);
return;
}
- for (i=0; notice_s[i]; i++) {
- gtk_text_buffer_insert_at_cursor (game->message_buffer, notice_s[i], -1);
- gtk_text_buffer_insert_at_cursor (game->message_buffer, " ", -1);
- }
- gtk_text_buffer_insert_at_cursor (game->message_buffer, "\n", -1);
- gtk_text_buffer_get_iter_at_offset (game->message_buffer,
- &game->message_iter,
- -1);
- gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (game->message_view),
- &game->message_iter,
- 0.0, FALSE, 0.0, 0.0);
-
- notice = rr_client_parse_notice (game->client, notice_s);
- if (notice == NULL) {
- int i;
- fprintf (stderr, "Failed to parse notice: ");
- for (i=0; notice_s[i]; i++)
- fprintf (stderr, " %s", notice_s[i]);
- fprintf (stderr, "\n");
- return;
- }
switch (notice->type) {
case RR_NOTICE_USER:
+ grr_game_printf (game,
+ "\nGLOBAL: %s has connected.", notice->u.string);
+ break;
case RR_NOTICE_QUIT:
+ grr_game_printf (game,
+ "\nGLOBAL: %s has disconnected.", notice->u.string);
+ break;
case RR_NOTICE_GAME:
+ grr_game_printf (game,
+ "\nGLOBAL: New game available: %s.", notice->u.string);
+ break;
case RR_NOTICE_DISPOSE:
+ grr_game_printf (game,
+ "\nGLOBAL: Game %s has been disposed.", notice->u.string);
+ break;
case RR_NOTICE_MESSAGE:
+ grr_game_printf (game, "\n%s> %s",
+ notice->u.message.username,
+ notice->u.message.text);
+ break;
case RR_NOTICE_GAMESTATE:
+ grr_game_printf (game, "\nGame state changed to: %s.",
+ rr_gamestate_str (notice->u.gamestate));
+ break;
case RR_NOTICE_JOIN:
+ grr_game_printf (game, "\nUser %s has joined the game.",
+ notice->u.string);
+ break;
case RR_NOTICE_WATCH:
+ grr_game_printf (game, "\nUser %s has started watching the game.",
+ notice->u.string);
+ break;
case RR_NOTICE_PART:
+ grr_game_printf (game, "\nUser %s has left the game.",
+ notice->u.string);
+ break;
case RR_NOTICE_BID:
+ grr_game_printf (game, "\nUser %s bids %d.",
+ notice->u.bid.username,
+ notice->u.bid.number);
+ break;
case RR_NOTICE_REVOKE:
- case RR_NOTICE_TIMER:
+ grr_game_printf (game, "\nUser %s revokes previous bid.",
+ notice->u.string);
+ break;
case RR_NOTICE_ABANDON:
+ grr_game_printf (game, "\nUser %s is willing to abandon this turn.",
+ notice->u.string);
+ break;
case RR_NOTICE_NOBID:
- case RR_NOTICE_ACTIVE:
+ grr_game_printf (game, "\nUser %s sees no point in bidding further this round",
+ notice->u.string);
+ break;
case RR_NOTICE_MOVE:
+ if (game->msg_id == game->last_move_msg_id
+ && game->last_move_robot == notice->u.move.robot) {
+ game->last_move_msg_id = grr_game_printf (game, " %s",
+ rr_direction_str (notice->u.move.direction));
+ } else {
+ game->last_move_msg_id = grr_game_printf (game, "\nMove #%d: %s %s",
+ notice->u.move.count,
+ rr_robot_str (notice->u.move.robot),
+ rr_direction_str (notice->u.move.direction));
+ game->last_move_robot = notice->u.move.robot;
+ }
+ break;
case RR_NOTICE_UNDO:
+ grr_game_print (game, "\nUNDO");
+ break;
case RR_NOTICE_RESET:
+ grr_game_print (game, "\nRESET");
+ break;
case RR_NOTICE_SCORE:
+ grr_game_printf (game, "\nScore for %s: %d.",
+ notice->u.bid.username,
+ notice->u.bid.number);
+ break;
case RR_NOTICE_ACTIVATE:
- /* XXX: Need to actually handle many of these. */
- fprintf (stderr, "Warning: Ignoring notice of type %d\n", notice->type);
+ grr_game_printf (game, "\nYour turn.",
+ notice->u.number);
+ break;
+ case RR_NOTICE_ACTIVE:
+ grr_game_printf (game, "\nUser %s now active to demonstrate solution in %d moves.",
+ notice->u.bid.username,
+ notice->u.bid.number);
+ break;
+ case RR_NOTICE_TIMER:
+ grr_game_printf (game, "\nTime remaining: %d seconds.",
+ notice->u.number);
break;
case RR_NOTICE_POSITION:
rr_board_position (board, notice->u.position.robot,
gtk_widget_queue_draw (GTK_WIDGET (game->window));
break;
case RR_NOTICE_TURN:
+ grr_game_print (game, "\nNew round!");
rr_board_set_goal_target (board, notice->u.target);
gtk_widget_queue_draw (GTK_WIDGET (game->window));
break;
status = rr_client_request (game->client, entry_text, &response);
if (status) {
- gtk_text_buffer_insert_at_cursor (game->message_buffer,
- "ERROR: ", -1);
- gtk_text_buffer_insert_at_cursor (game->message_buffer,
- rr_status_str (status), -1);
- gtk_text_buffer_insert_at_cursor (game->message_buffer,
- "\n", -1);
+ grr_game_printf (game, "\nERROR: %s.", rr_status_str (status));
} else {
- for (i=0; response[i]; i++) {
- gtk_text_buffer_insert_at_cursor (game->message_buffer,
- response[i], -1);
- gtk_text_buffer_insert_at_cursor (game->message_buffer,
- " ", -1);
+ if (response[0]) {
+ grr_game_print (game, "\n");
+ for (i=0; response[i]; i++)
+ grr_game_printf (game, "%s ", response[i]);
}
- gtk_text_buffer_insert_at_cursor (game->message_buffer, "\n", -1);
}
gtk_entry_set_text (GTK_ENTRY (game->command_entry), "");
}
+static int
+grr_game_printf (grr_game_t *game, const char *fmt, ...)
+{
+ int msg_id;
+
+ va_list ap;
+
+ va_start (ap, fmt);
+ msg_id = grr_game_vprintf (game, fmt, ap);
+ va_end (ap);
+
+ return msg_id;
+}
+
+static int
+grr_game_vprintf (grr_game_t *game, const char *fmt, va_list ap)
+{
+ char *msg;
+ int msg_id;
+
+ grr_sprintf_alloc_va (&msg, fmt, ap);
+ if (msg == NULL)
+ return 0;
+
+ msg_id = grr_game_print (game, msg);
+
+ free (msg);
+
+ return msg_id;
+}
+
+static int
+grr_game_print (grr_game_t *game, const char *msg)
+{
+ GtkTextIter iter;
+ GtkTextMark *mark;
+
+ /* There might be a lighter way to do this, but this seems to
+ work. */
+
+ gtk_text_buffer_get_end_iter (game->message_buffer, &iter);
+
+ mark = gtk_text_buffer_get_mark (game->message_buffer, "end");
+
+ gtk_text_buffer_move_mark (game->message_buffer, mark, &iter);
+
+ gtk_text_buffer_insert (game->message_buffer, &iter, msg, -1);
+
+ gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (game->message_view),
+ mark, 0.0, TRUE, 0.0, 1.0);
+
+ return ++game->msg_id;
+}
+
static int
grr_game_start_gui (grr_game_t *game)
{
vbox = gtk_vbox_new (FALSE, 1);
gtk_container_add (GTK_CONTAINER (window), vbox);
{
+ GtkTextIter iter;
game->board_view = grr_board_view_new (game->board);
grr_board_view_set_client (GRR_BOARD_VIEW (game->board_view), game->client);
game->message_buffer = gtk_text_buffer_new (NULL);
+ gtk_text_buffer_get_iter_at_offset (game->message_buffer,
+ &iter, -1);
+ gtk_text_buffer_create_mark (game->message_buffer,
+ "end", &iter, FALSE);
game->message_view = gtk_text_view_new_with_buffer (game->message_buffer);
game->command_entry = gtk_entry_new ();
--- /dev/null
+*.svgz
+.deps
+Makefile
+Makefile.in
+bin2cstring
+grr_icon_svg.h
--- /dev/null
+noinst_HEADERS=grr_icon_svg.h
+
+noinst_PROGRAMS = bin2cstring
+
+bin2cstring_SOURCES = bin2cstring.c
+
+pkgdata_DATA = \
+cell.svg \
+robot_blue.svg \
+robot_green.svg \
+robot_red.svg \
+robot_yellow.svg \
+target_blue_circle.svg \
+target_blue_octagon.svg \
+target_blue_square.svg \
+target_blue_triangle.svg \
+target_green_circle.svg \
+target_green_octagon.svg \
+target_green_square.svg \
+target_green_triangle.svg \
+target_red_circle.svg \
+target_red_octagon.svg \
+target_red_square.svg \
+target_red_triangle.svg \
+target_whirl.svg \
+target_yellow_circle.svg \
+target_yellow_octagon.svg \
+target_yellow_square.svg \
+target_yellow_triangle.svg \
+wall.svg
+
+grr_icon_svg.h: \
+cell.svgz \
+robot_blue.svgz \
+robot_green.svgz \
+robot_red.svgz \
+robot_yellow.svgz \
+target_blue_circle.svgz \
+target_blue_octagon.svgz \
+target_blue_square.svgz \
+target_blue_triangle.svgz \
+target_green_circle.svgz \
+target_green_octagon.svgz \
+target_green_square.svgz \
+target_green_triangle.svgz \
+target_red_circle.svgz \
+target_red_octagon.svgz \
+target_red_square.svgz \
+target_red_triangle.svgz \
+target_whirl.svgz \
+target_yellow_circle.svgz \
+target_yellow_octagon.svgz \
+target_yellow_square.svgz \
+target_yellow_triangle.svgz \
+wall.svgz
+ rm -f $@
+ for svgz in $^; do \
+ echo -n "char " >> $@; \
+ echo -n "grr_icon_svg_$${svgz/.svgz/}[] = " | tr "a-z" "A-Z" >> $@; \
+ ./bin2cstring $$svgz >> $@; \
+ echo ";" >> $@; \
+ done
+
+
+%.svgz: %.svg
+ gzip -c $< > $@
--- /dev/null
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+
+int
+main (int argc, char *argv[])
+{
+ int i, c;
+ FILE *file;
+
+ for (i=1; i < argc; i++) {
+ file = fopen (argv[i], "r");
+ if (file == NULL) {
+ fprintf (stderr, "Failed to open file %s: %s\n",
+ argv[i], strerror (errno));
+ continue;
+ }
+
+ putchar ('"');
+ while (1) {
+ c = fgetc (file);
+ if (c == EOF)
+ break;
+
+ if (isprint (c) && ! isspace (c))
+ printf ("%c", c);
+ else
+ printf ("\\%03o", c);
+ }
+ putchar ('"');
+ }
+
+ return 0;
+}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
-"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
-<!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
-<svg
- id="svg101"
- sodipodi:version="0.31"
- width="210mm"
- height="297mm"
- sodipodi:docname="w.svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:xlink="http://www.w3.org/1999/xlink">
- <defs
- id="defs103" />
- <sodipodi:namedview
- id="base"
- showgrid="true"
- snaptogrid="true"
- gridspacingy="0.19685in"
- gridspacingx="0.2in"
- gridoriginy="0.16in" />
- <path
- style="stroke:black;stroke-width:0.125;fill:none;"
- d="M 0 0
- C 1.08021 0.246551 0.762403 1.52281 0 2
- C -1.61026 3.00786 -3.51041 1.56445 -4 0
- C -4.86654 -2.76894 -2.6565 -5.44577 0 -6
- C 3.87403 -6.80825 7.41403 -3.74481 8 0
- C 8.77753 4.96904 4.83317 9.39499 0 10
- C -6.06102 10.7587 -11.3823 5.92184 -12 0
- C -12.7461 -7.15182 -7.01075 -13.3731 0 -14
- C 8.24206 -14.737 15.3663 -8.09982 16 0"/>
- <path
- transform="matrix(0.707107,-0.707107,0.707107,0.707107,0,0)"
- style="stroke:black;stroke-width:0.125;fill:none;"
- d="M 0 0
- C 1.08021 0.246551 0.762403 1.52281 0 2
- C -1.61026 3.00786 -3.51041 1.56445 -4 0
- C -4.86654 -2.76894 -2.6565 -5.44577 0 -6
- C 3.87403 -6.80825 7.41403 -3.74481 8 0
- C 8.77753 4.96904 4.83317 9.39499 0 10
- C -6.06102 10.7587 -11.3823 5.92184 -12 0
- C -12.7461 -7.15182 -7.01075 -13.3731 0 -14
- C 8.24206 -14.737 15.3663 -8.09982 16 0"/>
- <path
- style="stroke:black;stroke-width:0.125;fill:none;"
- d="M 11.3137 -11.3137 C 14.4363 -8.19113 16 -4.416 16 0"/>
-</svg>
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
-"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
-<svg width="744.094" height="1052.36">
- <path style="fill:red;stroke:none;"
- d="M 34 39
- C 37.25 40.055 36.145 43.645 34 44.987
- C 29.471 47.821 24.127 43.762 22.75 39
- C 20.313 31.574 26.529 24.045 34 22.487
- C 44.896 20.213 54.852 28.829 56.5 39
- C 58.687 53.337 47.594 65.785 34 67.487
- C 16.954 69.621 1.988 56.017 0 39
- C -1.848 19.247 14.283 1.75 34 0
- C 57.181 -2.086 77.218 16.581 79 39
- C 79.156 69.947 52.437 84.323 34 84
- C 56.775 82.5 75.372 62.399 73.219 39.225
- C 71.388 19.513 53.834 3.443 33.727 5.612
- C 17.078 7.407 3.526 22.42 5.719 39.459
- C 7.468 53.047 19.954 64.097 33.922 61.862
- C 44.449 60.177 53.03 50.191 50.719 39.303
- C 49.134 31.837 41.584 25.647 33.805 28.112
- C 29.41 29.504 25.369 34.862 28.219 39.381
- C 29.569 41.521 33.25 42.25 34 39"/>
- <g transform="translate(34,39),rotate(90),translate(-34,-39)">
- <path style="fill:blue;stroke:none;"
- d="M 34 39
- C 37.25 40.055 36.145 43.645 34 44.987
- C 29.471 47.821 24.127 43.762 22.75 39
- C 20.313 31.574 26.529 24.045 34 22.487
- C 44.896 20.213 54.852 28.829 56.5 39
- C 58.687 53.337 47.594 65.785 34 67.487
- C 16.954 69.621 1.988 56.017 0 39
- C -1.848 19.247 14.283 1.75 34 0
- C 57.181 -2.086 77.218 16.581 79 39
- C 79.156 69.947 52.437 84.323 34 84
- C 56.775 82.5 75.372 62.399 73.219 39.225
- C 71.388 19.513 53.834 3.443 33.727 5.612
- C 17.078 7.407 3.526 22.42 5.719 39.459
- C 7.468 53.047 19.954 64.097 33.922 61.862
- C 44.449 60.177 53.03 50.191 50.719 39.303
- C 49.134 31.837 41.584 25.647 33.805 28.112
- C 29.41 29.504 25.369 34.862 28.219 39.381
- C 29.569 41.521 33.25 42.25 34 39"/>
- </g>
- <g transform="translate(34,39),rotate(180),translate(-34,-39)">
- <path style="fill:green;stroke:none;"
- d="M 34 39
- C 37.25 40.055 36.145 43.645 34 44.987
- C 29.471 47.821 24.127 43.762 22.75 39
- C 20.313 31.574 26.529 24.045 34 22.487
- C 44.896 20.213 54.852 28.829 56.5 39
- C 58.687 53.337 47.594 65.785 34 67.487
- C 16.954 69.621 1.988 56.017 0 39
- C -1.848 19.247 14.283 1.75 34 0
- C 57.181 -2.086 77.218 16.581 79 39
- C 79.156 69.947 52.437 84.323 34 84
- C 56.775 82.5 75.372 62.399 73.219 39.225
- C 71.388 19.513 53.834 3.443 33.727 5.612
- C 17.078 7.407 3.526 22.42 5.719 39.459
- C 7.468 53.047 19.954 64.097 33.922 61.862
- C 44.449 60.177 53.03 50.191 50.719 39.303
- C 49.134 31.837 41.584 25.647 33.805 28.112
- C 29.41 29.504 25.369 34.862 28.219 39.381
- C 29.569 41.521 33.25 42.25 34 39"/>
- </g>
- <g transform="translate(34,39),rotate(270),translate(-34,-39)">
- <path style="fill:yellow;stroke:none;"
- d="M 34 39
- C 37.25 40.055 36.145 43.645 34 44.987
- C 29.471 47.821 24.127 43.762 22.75 39
- C 20.313 31.574 26.529 24.045 34 22.487
- C 44.896 20.213 54.852 28.829 56.5 39
- C 58.687 53.337 47.594 65.785 34 67.487
- C 16.954 69.621 1.988 56.017 0 39
- C -1.848 19.247 14.283 1.75 34 0
- C 57.181 -2.086 77.218 16.581 79 39
- C 79.156 69.947 52.437 84.323 34 84
- C 56.775 82.5 75.372 62.399 73.219 39.225
- C 71.388 19.513 53.834 3.443 33.727 5.612
- C 17.078 7.407 3.526 22.42 5.719 39.459
- C 7.468 53.047 19.954 64.097 33.922 61.862
- C 44.449 60.177 53.03 50.191 50.719 39.303
- C 49.134 31.837 41.584 25.647 33.805 28.112
- C 29.41 29.504 25.369 34.862 28.219 39.381
- C 29.569 41.521 33.25 42.25 34 39"/>
- </g>
- </svg>
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
-"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
-<svg>
- <path
- style="fill:none;stroke:black;stroke-width:1"
- d="M 0 0 C 1.08021 0.246551 0.762403 1.52281 0 2 C -1.61026 3.00786 -3.51041 1.56445 -4 0 C -4.86654 -2.76894 -2.6565 -5.44577 0 -6 C 3.87403 -6.80825 7.41403 -3.74481 8 0 C 8.77753 4.96904 4.83317 9.39499 0 10 C -6.06102 10.7587 -11.3823 5.92184 -12 0 C -12.7461 -7.15182 -7.01075 -13.3731 0 -14 C 8.24206 -14.737 15.3663 -8.09982 16 0 "/>
- <path
- transform="matrix(0,-1,1,0,0,0)"
- style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.125;"
- d="M 0 0 C 1.08021 0.246551 0.762403 1.52281 0 2 C -1.61026 3.00786 -3.51041 1.56445 -4 0 C -4.86654 -2.76894 -2.6565 -5.44577 0 -6 C 3.87403 -6.80825 7.41403 -3.74481 8 0 C 8.77753 4.96904 4.83317 9.39499 0 10 C -6.06102 10.7587 -11.3823 5.92184 -12 0 C -12.7461 -7.15182 -7.01075 -13.3731 0 -14 C 8.24206 -14.737 15.3663 -8.09982 16 0 "
- id="path113" />
- <path
- style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.125;"
- d="M 8.61478 12.5872 L 8.61478 12.5872 z "
- id="path112" />
- <path
- style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.125;"
- d="M -1.2246e-06 -16 C 8.832 -16 16 -8.832 16 -1.2246e-06 C 16 -7.94261e-07 16 -4.30343e-07 16 -3.91874e-15 L 0 0 L -1.2246e-06 -16 z "
- id="path108" />
-</svg>
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
-"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
-<svg>
- <path
- style="fill:none;stroke:black;stroke-width:1"
- d="M 0 0 C 1.08021 0.246551 0.762403 1.52281 0 2 C -1.61026 3.00786 -3.51041 1.56445 -4 0 C -4.86654 -2.76894 -2.6565 -5.44577 0 -6 C 3.87403 -6.80825 7.41403 -3.74481 8 0 C 8.77753 4.96904 4.83317 9.39499 0 10 C -6.06102 10.7587 -11.3823 5.92184 -12 0 C -12.7461 -7.15182 -7.01075 -13.3731 0 -14 C 8.24206 -14.737 15.3663 -8.09982 16 0 "/>
- <path
- transform="matrix(0,-1,1,0,0,0)"
- style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.125;"
- d="M 0 0 C 1.08021 0.246551 0.762403 1.52281 0 2 C -1.61026 3.00786 -3.51041 1.56445 -4 0 C -4.86654 -2.76894 -2.6565 -5.44577 0 -6 C 3.87403 -6.80825 7.41403 -3.74481 8 0 C 8.77753 4.96904 4.83317 9.39499 0 10 C -6.06102 10.7587 -11.3823 5.92184 -12 0 C -12.7461 -7.15182 -7.01075 -13.3731 0 -14 C 8.24206 -14.737 15.3663 -8.09982 16 0 "
- id="path113" />
- <path
- style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.125;"
- d="M 8.61478 12.5872 L 8.61478 12.5872 z "
- id="path112" />
- <path
- style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.125;"
- d="M -1.2246e-06 -16 C 8.832 -16 16 -8.832 16 -1.2246e-06 C 16 -7.94261e-07 16 -4.30343e-07 16 -3.91874e-15 L 0 0 L -1.2246e-06 -16 z "
- id="path108" />
-</svg>