summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am48
-rw-r--r--lib/cursesplugin.c599
-rw-r--r--lib/cursesplugin.h69
-rw-r--r--lib/textplugin.c444
-rw-r--r--lib/textplugin.h63
-rw-r--r--lib/x11plugin.c840
-rw-r--r--lib/x11plugin.h102
-rw-r--r--lib/xpm/Makefile.am31
-rw-r--r--lib/xpm/baddie.xpm28
-rw-r--r--lib/xpm/food.xpm27
-rw-r--r--lib/xpm/prize.xpm31
-rw-r--r--lib/xpm/robot.xpm28
-rw-r--r--lib/xpm/robot_east.xpm28
-rw-r--r--lib/xpm/robot_north.xpm28
-rw-r--r--lib/xpm/robot_south.xpm28
-rw-r--r--lib/xpm/robot_west.xpm28
-rw-r--r--lib/xpm/space.xpm26
-rw-r--r--lib/xpm/statusbar.xpm58
-rw-r--r--lib/xpm/wall.xpm26
19 files changed, 2532 insertions, 0 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..f3d6283
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,48 @@
+##
+## lib/Makefile.am
+##
+## GNU Robots is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## GNU Robots is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with GNU Robots; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+
+SUBDIRS = xpm
+
+if USE_CURSES
+CURSES_PLUGIN=libgrobots-curses.la
+else
+CURSES_PLUGIN=
+endif
+
+if USE_X11
+X11_PLUGIN=libgrobots-x11.la
+else
+X11_PLUGIN=
+endif
+
+INCLUDES = $(GLIB2_CFLAGS) $(CURSES_CFLAGS) $(X_FLAGS) -I$(top_builddir)/include
+
+pkglib_LTLIBRARIES = libgrobots-text.la $(CURSES_PLUGIN) $(X11_PLUGIN)
+
+libgrobots_text_la_SOURCES = textplugin.c
+libgrobots_text_la_LDFLAGS = -module -avoid-version
+libgrobots_text_la_LIBADD = $(GLIB2_LIBS)
+
+libgrobots_curses_la_SOURCES = cursesplugin.c
+libgrobots_curses_la_LDFLAGS = -module -avoid-version
+libgrobots_curses_la_LIBADD = $(GLIB2_LIBS) $(CURSES_LIBS)
+
+libgrobots_x11_la_SOURCES = x11plugin.c
+libgrobots_x11_la_LDFLAGS = -module -avoid-version
+libgrobots_x11_la_LIBADD = $(GLIB2_LIBS) $(X_LIBS)
+
diff --git a/lib/cursesplugin.c b/lib/cursesplugin.c
new file mode 100644
index 0000000..a3f08ad
--- /dev/null
+++ b/lib/cursesplugin.c
@@ -0,0 +1,599 @@
+/* $Id: cursesplugin.c,v 1.1 2004/10/21 19:24:30 zeenix Exp $ */
+
+/* GNU Robots game engine. */
+
+/* Copyright (C) 1998 Jim Hall, jhall1@isd.net */
+
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib.h>
+#include <stdio.h>
+#include "configs.h"
+#include "cursesplugin.h"
+
+enum
+{
+ ARG_0,
+ ARG_MAP
+};
+
+GType _curses_plugin_type = 0;
+static GType _parent_type = 0;
+
+static void curses_plugin_class_init (CursesPluginClass * klass);
+static void curses_plugin_init (GObject * object);
+static void curses_plugin_interface_init (gpointer g_iface, gpointer iface_data);
+
+static GObject * curses_plugin_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties);
+
+static void curses_plugin_finalize (GObject * object);
+static void curses_plugin_dispose (GObject * object);
+
+static void curses_plugin_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+
+static void curses_plugin_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+inline void curses_plugin_update_status (CursesPlugin *curses,
+ const gchar *s,
+ glong energy,
+ glong score,
+ glong shields);
+
+static GObjectClass *parent_class = NULL;
+
+GType
+curses_plugin_get_type (void)
+{
+ if (!_curses_plugin_type) {
+ static const GTypeInfo object_info = {
+ sizeof (CursesPluginClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) curses_plugin_class_init,
+ NULL,
+ NULL,
+ sizeof (CursesPlugin),
+ 0,
+ (GInstanceInitFunc) curses_plugin_init,
+ NULL
+ };
+
+ static const GInterfaceInfo interface_info = {
+ (GInterfaceInitFunc) curses_plugin_interface_init,
+ NULL,
+ NULL
+ };
+
+ _curses_plugin_type =
+ g_type_register_static (G_TYPE_OBJECT,
+ "CursesPlugin",
+ &object_info,
+ 0);
+
+ g_type_add_interface_static (_curses_plugin_type,
+ _parent_type,
+ &interface_info);
+ }
+
+ return _curses_plugin_type;
+}
+
+static void
+curses_plugin_class_init (CursesPluginClass * klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass *) klass;
+
+ parent_class = g_type_class_ref (G_TYPE_OBJECT);
+
+ gobject_class->constructor = curses_plugin_constructor;
+ gobject_class->set_property = curses_plugin_set_property;
+ gobject_class->get_property = curses_plugin_get_property;
+ gobject_class->dispose = curses_plugin_dispose;
+ gobject_class->finalize = curses_plugin_finalize;
+
+ g_object_class_override_property (gobject_class, ARG_MAP, "map");
+}
+
+static void
+curses_plugin_init (GObject * object)
+{
+ CursesPlugin *curses = CURSES_PLUGIN (object);
+
+ curses->map = NULL;
+ curses->map_size = NULL;
+}
+
+static GObject *
+curses_plugin_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ CursesPlugin *curses;
+
+ /* Chain up to the parent first */
+ object = parent_class->constructor (type, n_construct_properties, construct_properties);
+
+ curses = CURSES_PLUGIN (object);
+
+ /* Initialize curses mode */
+ gint color_pair;
+
+ curses->win = initscr ();
+
+ cbreak ();
+ noecho ();
+
+ scrollok (curses->win, TRUE); /* Put scrolling on */
+ setscrreg (LINES - 2, LINES - 1); /* Where to scroll */
+
+ //clearok (stdscr, TRUE);
+ nonl ();
+ intrflush (stdscr, FALSE);
+ keypad (stdscr, TRUE);
+
+ if (has_colors()) {
+ start_color();
+
+ /*
+ * Simple color assignment, often all we need.
+ **/
+ init_pair (COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
+ init_pair (COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
+ init_pair (COLOR_RED, COLOR_RED, COLOR_BLACK);
+ init_pair (COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
+ init_pair (COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
+ init_pair (COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair (COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
+ init_pair (COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
+ }
+
+ clear ();
+ refresh ();
+ curses->errors = 0;
+
+ return object;
+}
+
+static void
+curses_plugin_dispose (GObject * object)
+{
+ CursesPlugin *curses = CURSES_PLUGIN (object);
+
+ if (curses->map != NULL) {
+ g_object_unref (G_OBJECT (curses->map));
+
+ if (curses->map_size != NULL) {
+ g_free (curses->map_size);
+ }
+ }
+
+ parent_class->dispose (object);
+}
+
+/* finalize is called when the object has to free its resources */
+static void
+curses_plugin_finalize (GObject * object)
+{
+ /* End curses mode */
+ endwin ();
+
+ parent_class->finalize (object);
+}
+
+static void
+curses_plugin_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ CursesPlugin *curses;
+ GObject *obj;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (G_IS_CURSES_PLUGIN (object));
+
+ curses = CURSES_PLUGIN (object);
+
+ switch (prop_id) {
+ case ARG_MAP:
+ obj = g_value_get_object (value);
+ g_return_if_fail (obj != NULL);
+
+ if (curses->map != NULL) {
+ g_object_unref (curses->map);
+ }
+
+ curses->map = MAP (g_object_ref (obj));
+
+ if (curses->map_size != NULL) {
+ g_free (curses->map_size);
+ }
+
+ g_object_get (G_OBJECT (curses->map),
+ "size", &curses->map_size,
+ NULL);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+curses_plugin_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ CursesPlugin *curses;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (G_IS_CURSES_PLUGIN (object));
+
+ curses = CURSES_PLUGIN (object);
+
+ switch (prop_id) {
+ case ARG_MAP:
+ g_value_set_object (value, g_object_ref (G_OBJECT (curses->map)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+UserInterface *
+user_interface_new (Map *map, GType parent_type)
+{
+ g_return_val_if_fail (map != NULL, NULL);
+ g_return_val_if_fail (_parent_type != 0 || parent_type != 0, NULL);
+
+ if (!_parent_type) {
+ _parent_type = parent_type;
+ }
+
+ CursesPlugin *curses =
+ CURSES_PLUGIN (g_object_new (curses_plugin_get_type (),
+ "map", map,
+ NULL));
+ if (curses->errors) {
+ g_object_unref (G_OBJECT (curses));
+ return NULL;
+ }
+
+ return USER_INTERFACE (curses);
+}
+
+inline void curses_plugin_add_thing (CursesPlugin *curses,
+ gint x,
+ gint y,
+ gint thing)
+{
+ gshort color;
+
+ /* Highlight the unusual chars */
+ if (thing == '?') {
+ standout ();
+ }
+
+ switch (thing) {
+ case SPACE:
+ color = COLOR_PAIR (COLOR_BLACK);
+ break;
+ case FOOD:
+ color = COLOR_PAIR (COLOR_GREEN);
+ break;
+ case PRIZE:
+ color = COLOR_PAIR (COLOR_YELLOW);
+ break;
+ case WALL:
+ color = COLOR_PAIR (COLOR_WHITE);
+ break;
+ case BADDIE:
+ color = COLOR_PAIR (COLOR_RED);
+ break;
+ case ROBOT:
+ color = COLOR_PAIR (COLOR_BLUE);
+ break;
+ default:
+ /* What here? */
+ color = COLOR_PAIR (COLOR_BLACK);
+ }
+
+ mvaddch (y, x, thing | color);
+
+ if (thing == '?') {
+ standend ();
+ }
+
+ redrawwin (curses->win);
+}
+
+inline void curses_plugin_draw (CursesPlugin *curses)
+{
+ gshort color;
+ gint i, j;
+
+ /* Draw the map for the GNU Robots game. */
+
+ for (j = 0; j < curses->map_size->num_rows; j++) {
+ for (i = 0; i < curses->map_size->num_cols; i++) {
+ /* Special cases */
+
+ switch (MAP_GET_OBJECT (curses->map, i, j)) {
+ case '\0':
+ /* Highlight the unusual chars */
+ if (MAP_GET_OBJECT (curses->map, i, j) == '?') {
+ standout ();
+ }
+ color = COLOR_PAIR (COLOR_BLACK);
+ break;
+ case SPACE:
+ color = COLOR_PAIR (COLOR_BLACK);
+ break;
+ case FOOD:
+ color = COLOR_PAIR (COLOR_GREEN);
+ break;
+ case PRIZE:
+ color = COLOR_PAIR (COLOR_YELLOW);
+ break;
+ case WALL:
+ color = COLOR_PAIR (COLOR_WHITE);
+ break;
+ case BADDIE:
+ color = COLOR_PAIR (COLOR_RED);
+ break;
+ case ROBOT:
+ color = COLOR_PAIR (COLOR_BLUE);
+ break;
+ default:
+ /* What here? */
+ color = COLOR_PAIR (COLOR_BLACK);
+ break;
+ } /* switch */
+
+ mvaddch (j, i, MAP_GET_OBJECT (curses->map, i, j) | color);
+
+ if (MAP_GET_OBJECT (curses->map, i, j) == '?') {
+ standend ();
+ }
+ } /* for i */
+ } /* for j */
+
+ redrawwin (curses->win);
+}
+
+inline void curses_plugin_move_robot (CursesPlugin *curses,
+ gint from_x,
+ gint from_y,
+ gint to_x,
+ gint to_y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ /* Clear previous tile */
+
+ mvaddch (from_y, from_x, ' ' | COLOR_PAIR (COLOR_BLACK));
+
+ standout ();
+ switch (cdir) {
+ case NORTH:
+ mvaddch (to_y, to_x, '^' | COLOR_PAIR (COLOR_BLUE));
+ break;
+ case EAST:
+ mvaddch (to_y, to_x, '>' | COLOR_PAIR (COLOR_BLUE));
+ break;
+ case SOUTH:
+ mvaddch (to_y, to_x, 'v' | COLOR_PAIR (COLOR_BLUE));
+ break;
+ case WEST:
+ mvaddch (to_y, to_x, '<' | COLOR_PAIR (COLOR_BLUE));
+ break;
+ }
+
+ standend ();
+ refresh ();
+
+ g_usleep (USLEEP_TIME);
+}
+
+/* function to animate the robot */
+inline void curses_plugin_robot_smell (CursesPlugin *curses,
+ gint x,
+ gint y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ curses_plugin_update_status (curses, "robot smells...", energy, score, shields);
+}
+
+inline void curses_plugin_robot_zap (CursesPlugin *curses,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ curses_plugin_update_status (curses, "robot fires his little gun...", energy, score, shields);
+}
+
+inline void curses_plugin_robot_feel (CursesPlugin *curses,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ curses_plugin_update_status (curses, "robot feels for a thing...", energy, score, shields);
+}
+
+inline void curses_plugin_robot_grab (CursesPlugin *curses,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ curses_plugin_update_status (curses, "robot grabs thing...", energy, score, shields);
+}
+
+inline void curses_plugin_robot_look (CursesPlugin *curses,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ curses_plugin_update_status (curses, "robot looks for a thing...", energy, score, shields);
+}
+
+/* function to get data from user */
+inline void curses_plugin_get_string (CursesPlugin *curses,
+ gchar *prompt,
+ gchar *buff,
+ gint len)
+{
+ mvaddstr (LINES - 2, 0, prompt);
+ refresh ();
+
+ echo ();
+ getnstr (buff, len);
+ noecho ();
+
+ move (LINES - 2, 0);
+ clrtoeol ();
+ refresh ();
+}
+
+inline void curses_plugin_update_status (CursesPlugin *curses,
+ const gchar *s,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ /* print on mode line (y=LINES-1) */
+ mvaddstr (LINES - 1, 1, s);
+ refresh ();
+
+ /* Sleep, then erase it */
+ napms (SLEEP_TIME);
+
+ move (LINES - 1, 1);
+ clrtoeol ();
+ refresh ();
+}
+
+static void curses_plugin_interface_init (gpointer g_iface, gpointer iface_data)
+{
+ UserInterfaceClass *klass = (UserInterfaceClass *)g_iface;
+
+ klass->user_interface_add_thing = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint thing))
+ curses_plugin_add_thing;
+
+ klass->user_interface_draw = (void (*) (UserInterface *ui)) curses_plugin_draw;
+ klass->user_interface_update_status = (void (*) (UserInterface *ui,
+ const gchar *s,
+ glong energy,
+ glong score,
+ glong shields))
+ curses_plugin_update_status;
+ klass->user_interface_move_robot = (void (*) (UserInterface *ui,
+ gint from_x,
+ gint from_y,
+ gint to_x,
+ gint to_y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields))
+ curses_plugin_move_robot;
+ klass->user_interface_robot_smell = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields))
+ curses_plugin_robot_smell;
+ klass->user_interface_robot_zap = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ curses_plugin_robot_zap;
+ klass->user_interface_robot_feel = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ curses_plugin_robot_grab;
+ klass->user_interface_robot_grab = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ curses_plugin_robot_grab;
+ klass->user_interface_robot_look = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ curses_plugin_robot_look;
+ klass->user_interface_get_string = (void (*) (UserInterface *ui,
+ gchar *prompt,
+ gchar *buff,
+ gint len))
+ curses_plugin_get_string;
+}
diff --git a/lib/cursesplugin.h b/lib/cursesplugin.h
new file mode 100644
index 0000000..7f72d0e
--- /dev/null
+++ b/lib/cursesplugin.h
@@ -0,0 +1,69 @@
+/* $Id: cursesplugin.h,v 1.1 2004/10/21 19:24:30 zeenix Exp $ */
+
+/* GNU Robots game engine. */
+
+/* Copyright (C) 1998 Jim Hall, jhall1@isd.net */
+
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __CURSES_PLUGIN_H__
+#define __CURSES_PLUGIN_H__
+
+#include <glib-object.h>
+#include <curses.h>
+#include <stdio.h>
+#include <stdlib.h> /* for sleep */
+#include "configs.h"
+#include "userinterface.h"
+#include "map.h"
+
+G_BEGIN_DECLS
+
+extern GType _curses_plugin_type;
+
+typedef struct _CursesPlugin CursesPlugin;
+
+struct _CursesPlugin {
+ GObject object;
+ Map *map;
+ MapSize *map_size;
+ gint errors;
+
+ WINDOW *win;
+};
+
+typedef struct _CursesPluginClass CursesPluginClass;
+
+struct _CursesPluginClass {
+ GObjectClass parent_class;
+};
+
+#define G_TYPE_CURSES_PLUGIN (_curses_plugin_type)
+#define G_IS_CURSES_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_CURSES_PLUGIN))
+#define G_IS_CURSES_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_CURSES_PLUGIN))
+#define CURSES_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_CURSES_PLUGIN, CursesPluginClass))
+#define CURSES_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_CURSES_PLUGIN, CursesPlugin))
+#define CURSES_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_CURSES_PLUGIN, CursesPluginClass))
+
+/* normal GObject stuff */
+GType curses_plugin_get_type (void);
+
+CursesPlugin* curses_plugin_new (void);
+
+G_END_DECLS
+
+#endif /* __CURSES_PLUGIN_H__*/
diff --git a/lib/textplugin.c b/lib/textplugin.c
new file mode 100644
index 0000000..32a5a56
--- /dev/null
+++ b/lib/textplugin.c
@@ -0,0 +1,444 @@
+/* $Id: textplugin.c,v 1.1 2004/10/21 19:24:30 zeenix Exp $ */
+
+/* GNU Robots game engine. */
+
+/* Copyright (C) 1998 Jim Hall, jhall1@isd.net */
+
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib.h>
+#include <stdio.h>
+#include "configs.h"
+#include "textplugin.h"
+
+enum
+{
+ ARG_0,
+ ARG_MAP
+};
+
+GType _text_plugin_type = 0;
+static GType _parent_type = 0;
+
+static void text_plugin_class_init (TextPluginClass * klass);
+static void text_plugin_init (GObject * object);
+static void text_plugin_interface_init (gpointer g_iface, gpointer iface_data);
+
+static GObject * text_plugin_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties);
+
+static void text_plugin_finalize (GObject * object);
+static void text_plugin_dispose (GObject * object);
+
+static void text_plugin_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+
+static void text_plugin_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+inline void text_plugin_update_status (TextPlugin *text,
+ const gchar *s,
+ glong energy,
+ glong score,
+ glong shields);
+
+static GObjectClass *parent_class = NULL;
+
+/* For translation of directions to strings */
+static gchar *str_dir[] = { "North", "East", "South", "West" };
+
+GType
+text_plugin_get_type (void)
+{
+ if (!_text_plugin_type) {
+ static const GTypeInfo object_info = {
+ sizeof (TextPluginClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) text_plugin_class_init,
+ NULL,
+ NULL,
+ sizeof (TextPlugin),
+ 0,
+ (GInstanceInitFunc) text_plugin_init,
+ NULL
+ };
+
+ static const GInterfaceInfo interface_info = {
+ (GInterfaceInitFunc) text_plugin_interface_init,
+ NULL,
+ NULL
+ };
+
+ _text_plugin_type =
+ g_type_register_static (G_TYPE_OBJECT,
+ "TextPlugin",
+ &object_info,
+ 0);
+
+ g_type_add_interface_static (_text_plugin_type,
+ _parent_type,
+ &interface_info);
+ }
+
+ return _text_plugin_type;
+}
+
+static void
+text_plugin_class_init (TextPluginClass * klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass *) klass;
+
+ parent_class = g_type_class_ref (G_TYPE_OBJECT);
+
+ gobject_class->constructor = text_plugin_constructor;
+ gobject_class->set_property = text_plugin_set_property;
+ gobject_class->get_property = text_plugin_get_property;
+ gobject_class->dispose = text_plugin_dispose;
+ gobject_class->finalize = text_plugin_finalize;
+
+ g_object_class_override_property (gobject_class, ARG_MAP, "map");
+}
+
+static void
+text_plugin_init (GObject * object)
+{
+ TextPlugin *text = TEXT_PLUGIN (object);
+
+ text->map = NULL;
+ text->map_size = NULL;
+}
+
+static GObject *
+text_plugin_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+
+ /* Chain up to the parent first */
+ object = parent_class->constructor (type, n_construct_properties, construct_properties);
+
+ g_printf ("GNU Robots starting..\n");
+
+ return object;
+}
+
+static void
+text_plugin_dispose (GObject * object)
+{
+ TextPlugin *text = TEXT_PLUGIN (object);
+
+ if (text->map != NULL) {
+ g_object_unref (G_OBJECT (text->map));
+
+ if (text->map_size != NULL) {
+ g_free (text->map_size);
+ }
+ }
+
+ parent_class->dispose (object);
+}
+
+/* finalize is called when the object has to free its resources */
+static void
+text_plugin_finalize (GObject * object)
+{
+ g_printf ("GNU Robots done.\n");
+
+ parent_class->finalize (object);
+}
+
+static void
+text_plugin_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ TextPlugin *text;
+ GObject *obj;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (G_IS_TEXT_PLUGIN (object));
+
+ text = TEXT_PLUGIN (object);
+
+ switch (prop_id) {
+ case ARG_MAP:
+ obj = g_value_get_object (value);
+ g_return_if_fail (obj != NULL);
+
+ if (text->map != NULL) {
+ g_object_unref (text->map);
+ }
+
+ text->map = MAP (g_object_ref (obj));
+
+ if (text->map_size != NULL) {
+ g_free (text->map_size);
+ }
+
+ g_object_get (G_OBJECT (text->map),
+ "size", &text->map_size,
+ NULL);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+text_plugin_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ TextPlugin *text;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (G_IS_TEXT_PLUGIN (object));
+
+ text = TEXT_PLUGIN (object);
+
+ switch (prop_id) {
+ case ARG_MAP:
+ g_value_set_object (value, g_object_ref (G_OBJECT (text->map)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+UserInterface *
+user_interface_new (Map *map, GType parent_type)
+{
+ g_return_val_if_fail (map != NULL, NULL);
+ g_return_val_if_fail (_parent_type != 0 || parent_type != 0, NULL);
+
+ if (!_parent_type) {
+ _parent_type = parent_type;
+ }
+
+ TextPlugin *text =
+ TEXT_PLUGIN (g_object_new (text_plugin_get_type (),
+ "map", map,
+ NULL));
+ if (text->errors) {
+ g_object_unref (G_OBJECT (text));
+ return NULL;
+ }
+
+ return USER_INTERFACE (text);
+}
+
+inline void text_plugin_add_thing (TextPlugin *text,
+ gint x,
+ gint y,
+ gint thing)
+{
+ g_printf ("thing `%c' added at %d,%d\n", thing, x, y);
+}
+
+inline void text_plugin_draw (TextPlugin *text)
+{
+ gint i, j;
+
+ for (j = 0; j < text->map_size->num_rows; j++) {
+ for (i = 0; i < text->map_size->num_cols; i++) {
+ g_printf ("thing `%c' added at %d,%d\n", MAP_GET_OBJECT (text->map, i, j), i, j);
+ }
+ }
+}
+
+inline void text_plugin_move_robot (TextPlugin *text,
+ gint from_x,
+ gint from_y,
+ gint x,
+ gint y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ g_printf ("robot now at %d,%d facing %s\n", x, y, str_dir[cdir]);
+}
+
+/* function to animate the robot */
+inline void text_plugin_robot_smell (TextPlugin *text,
+ gint x,
+ gint y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ g_printf ("the robot sniffs..\n");
+}
+
+inline void text_plugin_robot_zap (TextPlugin *text,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ g_printf ("robot fires gun at space %d,%d\n", x_to, y_to);
+}
+
+inline void text_plugin_robot_feel (TextPlugin *text,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ g_printf ("robot feels space %d,%d\n", x_to, y_to);
+}
+
+inline void text_plugin_robot_grab (TextPlugin *text,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ g_printf ("robot grabs for space %d,%d\n", x_to, y_to);
+}
+
+inline void text_plugin_robot_look (TextPlugin *text,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ g_printf ("robot looks towards %s from %d,%d\n", str_dir[cdir], x, y);
+}
+
+/* function to get data from user */
+inline void text_plugin_get_string (TextPlugin *text,
+ gchar *prompt,
+ gchar *buff,
+ gint len)
+{
+ fputs (prompt, stdout);
+ fgets (buff, len, stdin);
+}
+
+inline void text_plugin_update_status (TextPlugin *text,
+ const gchar *s,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ puts (s);
+}
+
+static void text_plugin_interface_init (gpointer g_iface, gpointer iface_data)
+{
+ UserInterfaceClass *klass = (UserInterfaceClass *)g_iface;
+
+ klass->user_interface_add_thing = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint thing))
+ text_plugin_add_thing;
+
+ klass->user_interface_draw = (void (*) (UserInterface *ui)) text_plugin_draw;
+ klass->user_interface_update_status = (void (*) (UserInterface *ui,
+ const gchar *s,
+ glong energy,
+ glong score,
+ glong shields))
+ text_plugin_update_status;
+ klass->user_interface_move_robot = (void (*) (UserInterface *ui,
+ gint from_x,
+ gint from_y,
+ gint to_x,
+ gint to_y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields))
+ text_plugin_move_robot;
+ klass->user_interface_robot_smell = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields))
+ text_plugin_robot_smell;
+ klass->user_interface_robot_zap = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ text_plugin_robot_zap;
+ klass->user_interface_robot_feel = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ text_plugin_robot_grab;
+ klass->user_interface_robot_grab = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ text_plugin_robot_grab;
+ klass->user_interface_robot_look = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ text_plugin_robot_look;
+ klass->user_interface_get_string = (void (*) (UserInterface *ui,
+ gchar *prompt,
+ gchar *buff,
+ gint len))
+ text_plugin_get_string;
+}
diff --git a/lib/textplugin.h b/lib/textplugin.h
new file mode 100644
index 0000000..fd9eb7b
--- /dev/null
+++ b/lib/textplugin.h
@@ -0,0 +1,63 @@
+/* $Id: textplugin.h,v 1.1 2004/10/21 19:24:30 zeenix Exp $ */
+
+/* GNU Robots game engine. */
+
+/* Copyright (C) 1998 Jim Hall, jhall1@isd.net */
+
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __TEXT_PLUGIN_H__
+#define __TEXT_PLUING_H__
+
+#include <glib-object.h>
+#include "userinterface.h"
+#include "map.h"
+
+G_BEGIN_DECLS
+
+extern GType _text_plugin_type;
+
+typedef struct _TextPlugin TextPlugin;
+
+struct _TextPlugin {
+ GObject object;
+ Map *map;
+ MapSize *map_size;
+ gint errors;
+};
+
+typedef struct _TextPluginClass TextPluginClass;
+
+struct _TextPluginClass {
+ GObjectClass parent_class;
+};
+
+#define G_TYPE_TEXT_PLUGIN (_text_plugin_type)
+#define G_IS_TEXT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_TEXT_PLUGIN))
+#define G_IS_TEXT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_TEXT_PLUGIN))
+#define TEXT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_TEXT_PLUGIN, TextPluginClass))
+#define TEXT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_TEXT_PLUGIN, TextPlugin))
+#define TEXT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_TEXT_PLUGIN, TextPluginClass))
+
+/* normal GObject stuff */
+GType text_plugin_get_type (void);
+
+TextPlugin* text_plugin_new (void);
+
+G_END_DECLS
+
+#endif /* __TEXT_PLUGIN_H__*/
diff --git a/lib/x11plugin.c b/lib/x11plugin.c
new file mode 100644
index 0000000..d40efd9
--- /dev/null
+++ b/lib/x11plugin.c
@@ -0,0 +1,840 @@
+/* $Id: x11plugin.c,v 1.1 2004/10/21 19:24:30 zeenix Exp $ */
+
+/* GNU Robots game engine. */
+
+/* Copyright (C) 1998 Jim Hall, jhall1@isd.net */
+
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib.h>
+#include <stdio.h>
+#include "configs.h"
+#include "x11plugin.h"
+
+enum
+{
+ ARG_0,
+ ARG_MAP
+};
+
+GType _x11_plugin_type = 0;
+static GType _parent_type = 0;
+
+static void x11_plugin_class_init (X11PluginClass * klass);
+static void x11_plugin_init (GObject * object);
+static void x11_plugin_interface_init (gpointer g_iface, gpointer iface_data);
+
+static GObject * x11_plugin_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties);
+
+static void x11_plugin_finalize (GObject * object);
+static void x11_plugin_dispose (GObject * object);
+
+static void x11_plugin_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+
+static void x11_plugin_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static void put_tile (X11Plugin *x11, XImage *image, gint x, gint y);
+static void put_winbuf (X11Plugin *x11);
+static void setup_winbuf (X11Plugin *x11);
+void create_image (X11Plugin *x11, gchar **data, XImage ** image);
+inline void x11_plugin_update_status (X11Plugin *x11,
+ const gchar *s,
+ glong energy,
+ glong score,
+ glong shields);
+
+static GObjectClass *parent_class = NULL;
+
+GType
+x11_plugin_get_type (void)
+{
+ if (!_x11_plugin_type) {
+ static const GTypeInfo object_info = {
+ sizeof (X11PluginClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) x11_plugin_class_init,
+ NULL,
+ NULL,
+ sizeof (X11Plugin),
+ 0,
+ (GInstanceInitFunc) x11_plugin_init,
+ NULL
+ };
+
+ static const GInterfaceInfo interface_info = {
+ (GInterfaceInitFunc) x11_plugin_interface_init,
+ NULL,
+ NULL
+ };
+
+ _x11_plugin_type =
+ g_type_register_static (G_TYPE_OBJECT,
+ "X11Plugin",
+ &object_info,
+ 0);
+
+ g_type_add_interface_static (_x11_plugin_type,
+ _parent_type,
+ &interface_info);
+ }
+
+ return _x11_plugin_type;
+}
+
+static void
+x11_plugin_class_init (X11PluginClass * klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass *) klass;
+
+ parent_class = g_type_class_ref (G_TYPE_OBJECT);
+
+ gobject_class->constructor = x11_plugin_constructor;
+ gobject_class->set_property = x11_plugin_set_property;
+ gobject_class->get_property = x11_plugin_get_property;
+ gobject_class->dispose = x11_plugin_dispose;
+ gobject_class->finalize = x11_plugin_finalize;
+
+ g_object_class_override_property (gobject_class, ARG_MAP, "map");
+}
+
+static void
+x11_plugin_init (GObject * object)
+{
+ X11Plugin *x11 = X11_PLUGIN (object);
+
+ x11->map = NULL;
+ x11->map_size = NULL;
+}
+
+static GObject *
+x11_plugin_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ /* Initialize X11 */
+ GObject *object;
+ X11Plugin *x11;
+#include "xpm/statusbar.xpm"
+#include "xpm/space.xpm"
+#include "xpm/food.xpm"
+#include "xpm/wall.xpm"
+#include "xpm/prize.xpm"
+#include "xpm/baddie.xpm"
+#include "xpm/robot_north.xpm"
+#include "xpm/robot_east.xpm"
+#include "xpm/robot_south.xpm"
+#include "xpm/robot_west.xpm"
+#include "xpm/robot.xpm"
+ Atom prots[6];
+ XClassHint classhint;
+ XWMHints wmhints;
+ XGCValues values;
+ Atom delete_win;
+ gint x;
+
+ /* Chain up to the parent first */
+ object = parent_class->constructor (type, n_construct_properties, construct_properties);
+
+ x11 = X11_PLUGIN (object);
+
+ if ((x11->dpy = XOpenDisplay ("")) == NULL) {
+ g_printf ("Couldn't open the X Server Display!\n");
+ exit (1); /* Exit nicely isn't needed yet, and causes segfault */
+ }
+
+ delete_win = XInternAtom (x11->dpy, "WM_DELETE_WINDOW", False);
+
+ x11->win_width = x11->map_size->num_cols * TILE_SIZE;
+ x11->win_height = x11->map_size->num_rows * TILE_SIZE + 32;
+ x11->x_win = XCreateSimpleWindow (x11->dpy, DefaultRootWindow (x11->dpy), 0, 0,
+ x11->win_width, x11->win_height, 0, 0, 0);
+
+ prots[0] = delete_win;
+ XSetWMProtocols (x11->dpy, x11->x_win, prots, 1);
+
+ XStoreName (x11->dpy, x11->x_win, "GNU Robots");
+
+ classhint.res_name = "robots";
+ classhint.res_class = "Robots";
+ XSetClassHint (x11->dpy, x11->x_win, &classhint);
+
+ /* XSetCommand() seems to segfault... */
+
+ wmhints.input = True;
+ wmhints.flags = InputHint;
+ XSetWMHints (x11->dpy, x11->x_win, &wmhints);
+
+ XSelectInput (x11->dpy, x11->x_win,
+ KeyPressMask | KeyReleaseMask | StructureNotifyMask | FocusChangeMask);
+
+ XMapWindow (x11->dpy, x11->x_win);
+
+ x11->text = XLoadFont (x11->dpy, "-*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*");
+ values.font = x11->text;
+ values.foreground = WhitePixel (x11->dpy, DefaultScreen (x11->dpy));
+
+ x11->gc = XCreateGC (x11->dpy, x11->x_win, GCFont | GCForeground, &values);
+
+ create_image (x11, statusbar_xpm, &x11->statusbar);
+ create_image (x11, space_xpm, &x11->space);
+ create_image (x11, food_xpm, &x11->food);
+ create_image (x11, wall_xpm, &x11->wall);
+ create_image (x11, prize_xpm, &x11->prize);
+ create_image (x11, baddie_xpm, &x11->baddie);
+ create_image (x11, robot_north_xpm, &x11->robotDirs[0]);
+ create_image (x11, robot_east_xpm, &x11->robotDirs[1]);
+ create_image (x11, robot_south_xpm, &x11->robotDirs[2]);
+ create_image (x11, robot_west_xpm, &x11->robotDirs[3]);
+ create_image (x11, robot_xpm, &x11->robotPix);
+
+ setup_winbuf (x11);
+
+ //update_status ("Welcome to GNU Robots");
+ x11->errors = 0;
+
+ return object;
+}
+
+static void
+x11_plugin_dispose (GObject * object)
+{
+ X11Plugin *x11 = X11_PLUGIN (object);
+
+ if (x11->map != NULL) {
+ g_object_unref (G_OBJECT (x11->map));
+
+ if (x11->map_size != NULL) {
+ g_free (x11->map_size);
+ }
+ }
+
+ parent_class->dispose (object);
+}
+
+/* finalize is called when the object has to free its resources */
+static void
+x11_plugin_finalize (GObject * object)
+{
+ X11Plugin *x11 = X11_PLUGIN (object);
+
+ /* End X11 mode */
+#ifdef USE_MITSHM
+ if (use_mitshm) {
+ XShmDetach (x11->dpy, &shm_info);
+ if (shm_info.shmaddr)
+ shmdt (shm_info.shmaddr);
+ if (shm_info.shmid >= 0)
+ shmctl (shm_info.shmid, IPC_RMID, 0);
+ }
+#endif
+ XDestroyWindow (x11->dpy, x11->x_win);
+ XUnloadFont (x11->dpy, x11->text);
+
+ parent_class->finalize (object);
+}
+
+static void
+x11_plugin_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ X11Plugin *x11;
+ GObject *obj;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (G_IS_X11_PLUGIN (object));
+
+ x11 = X11_PLUGIN (object);
+
+ switch (prop_id) {
+ case ARG_MAP:
+ obj = g_value_get_object (value);
+ g_return_if_fail (obj != NULL);
+
+ if (x11->map != NULL) {
+ g_object_unref (x11->map);
+ }
+
+ x11->map = MAP (g_object_ref (obj));
+
+ if (x11->map_size != NULL) {
+ g_free (x11->map_size);
+ }
+
+ g_object_get (G_OBJECT (x11->map),
+ "size", &x11->map_size,
+ NULL);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+x11_plugin_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ X11Plugin *x11;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (G_IS_X11_PLUGIN (object));
+
+ x11 = X11_PLUGIN (object);
+
+ switch (prop_id) {
+ case ARG_MAP:
+ g_value_set_object (value, g_object_ref (G_OBJECT (x11->map)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+UserInterface *
+user_interface_new (Map *map, GType parent_type)
+{
+ g_return_val_if_fail (map != NULL, NULL);
+ g_return_val_if_fail (_parent_type != 0 || parent_type != 0, NULL);
+
+ if (!_parent_type) {
+ _parent_type = parent_type;
+ }
+
+ X11Plugin *x11 =
+ X11_PLUGIN (g_object_new (x11_plugin_get_type (),
+ "map", map,
+ NULL));
+ if (x11->errors) {
+ g_object_unref (G_OBJECT (x11));
+ return NULL;
+ }
+
+ return USER_INTERFACE (x11);
+}
+
+/* note that hook_delete_thing(x,y) is the same as
+ hook_add_thing(x,y,space) */
+inline void x11_plugin_add_thing (X11Plugin *x11,
+ gint x,
+ gint y,
+ gint thing)
+{
+ gint w_x, w_y;
+
+ w_x = x * TILE_SIZE;
+ w_y = y * TILE_SIZE;
+
+ switch (thing) {
+ case SPACE:
+ put_tile (x11, x11->space, w_x, w_y);
+ break;
+ case FOOD:
+ put_tile (x11, x11->food, w_x, w_y);
+ break;
+ case PRIZE:
+ put_tile (x11, x11->prize, w_x, w_y);
+ break;
+ case WALL:
+ put_tile (x11, x11->wall, w_x, w_y);
+ break;
+ case BADDIE:
+ put_tile (x11, x11->baddie, w_x, w_y);
+ break;
+ case ROBOT:
+ put_tile (x11, x11->robotPix, w_x, w_y);
+ break;
+ default:
+ put_tile (x11, x11->wall, w_x, w_y);
+ break;
+ }
+
+ put_winbuf (x11);
+ XFlush (x11->dpy);
+}
+
+inline void x11_plugin_draw (X11Plugin *x11)
+{
+ gint i, j;
+
+ /* Draw the map for the GNU Robots game. */
+ for (j = 0; j < x11->map_size->num_rows; j++) {
+ for (i = 0; i < x11->map_size->num_cols; i++) {
+ /* Special cases */
+ switch (MAP_GET_OBJECT (x11->map, i, j)) {
+ /* Add something for the ROBOT?? */
+ case '\0':
+ put_tile (x11, x11->wall, i * TILE_SIZE, j * TILE_SIZE);
+ break;
+ case SPACE:
+ put_tile (x11, x11->space, i * TILE_SIZE, j * TILE_SIZE);
+ break;
+ case FOOD:
+ put_tile (x11, x11->food, i * TILE_SIZE, j * TILE_SIZE);
+ break;
+ case PRIZE:
+ put_tile (x11, x11->prize, i * TILE_SIZE, j * TILE_SIZE);
+ break;
+ case WALL:
+ put_tile (x11, x11->wall, i * TILE_SIZE, j * TILE_SIZE);
+ break;
+ case BADDIE:
+ put_tile (x11, x11->baddie, i * TILE_SIZE, j * TILE_SIZE);
+ break;
+ case ROBOT:
+ put_tile (x11, x11->robotPix, i * TILE_SIZE, j * TILE_SIZE);
+ break;
+ default:
+ put_tile (x11, x11->wall, i * TILE_SIZE, j * TILE_SIZE);
+ break;
+ } /* switch */
+ } /* for i */
+ } /* for j */
+
+ put_winbuf (x11);
+ XSync (x11->dpy, FALSE);
+}
+
+inline void x11_plugin_move_robot (X11Plugin *x11,
+ gint from_x,
+ gint from_y,
+ gint to_x,
+ gint to_y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ const static gint movement = TILE_SIZE / 16;
+ guint8 distance = dist (from_x, from_y, to_x, to_y);
+ guint w_x = to_x * TILE_SIZE, w_y = to_y * TILE_SIZE, tw_x, tw_y;
+ Bool ok;
+
+ g_assert (distance <= 1);
+
+ x11_plugin_update_status (x11, "robot moves..", energy, score, shields);
+
+ /* Check if robot is moving withing a single box */
+ if (distance == 0) {
+ put_tile (x11, x11->space, from_x * TILE_SIZE, from_y * TILE_SIZE);
+ put_tile (x11, x11->robotDirs[cdir], to_x * TILE_SIZE, to_y * TILE_SIZE);
+
+ put_winbuf (x11);
+ XSync (x11->dpy, False);
+ g_usleep (USLEEP_TIME / 16);
+
+ return;
+ }
+
+ from_x *= TILE_SIZE;
+ from_y *= TILE_SIZE;
+ tw_y = w_y;
+ tw_x = w_x;
+ switch (cdir) {
+ case NORTH:
+ tw_y = from_y - movement;
+ break;
+ case SOUTH:
+ tw_y = from_y + movement;
+ break;
+ case EAST:
+ tw_x = from_x + movement;
+ break;
+ case WEST:
+ tw_x = from_x - movement;
+ break;
+ default:
+ g_printf ("Weird unknown robot direction. I'm Confused.\n");
+ }
+
+ while (1) {
+ put_tile (x11, x11->space, from_x, from_y);
+ put_tile (x11, x11->robotDirs[cdir], tw_x, tw_y);
+
+ ok = False;
+ if (tw_x < w_x) {
+ tw_x += movement;
+ ok = True;
+ } else if (tw_x > w_x) {
+ tw_x -= movement;
+ ok = True;
+ }
+ if (tw_y < w_y) {
+ tw_y += movement;
+ ok = True;
+ } else if (tw_y > w_y) {
+ tw_y -= movement;
+ ok = True;
+ }
+ put_winbuf (x11);
+ XSync (x11->dpy, False);
+ g_usleep (USLEEP_TIME / 16);
+ if (!ok)
+ break;
+ }
+
+ g_usleep (USLEEP_TIME);
+}
+
+/* hooks to animate the robot */
+inline void x11_plugin_robot_smell (X11Plugin *x11,
+ gint x,
+ gint y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ /* If we want to change the pic, do it here */
+ x11_plugin_update_status (x11, "robot sniffs...", energy, score, shields);
+ g_usleep (USLEEP_TIME);
+}
+
+inline void x11_plugin_robot_zap (X11Plugin *x11,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ x11_plugin_update_status (x11, "robot fires his little gun...", energy, score, shields);
+ g_usleep (USLEEP_TIME);
+}
+
+inline void x11_plugin_robot_feel (X11Plugin *x11,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ x11_plugin_update_status (x11, "robot feels for a thing...", energy, score, shields);
+ g_usleep (USLEEP_TIME);
+}
+
+inline void x11_plugin_robot_grab (X11Plugin *x11,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ x11_plugin_update_status (x11, "robot grabs thing...", energy, score, shields);
+ g_usleep (USLEEP_TIME);
+}
+
+inline void x11_plugin_robot_look (X11Plugin *x11,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ x11_plugin_update_status (x11, "robot looks for a thing...", energy, score, shields);
+ g_usleep (USLEEP_TIME);
+}
+
+/* hooks to get/display data from/to user */
+inline void x11_plugin_get_string (X11Plugin *x11,
+ gchar *prompt,
+ gchar *buff,
+ gint len)
+{
+ /* You want me to write a text-box using xlib?
+ * You got to be kidding me
+ * */
+ fputs (prompt, stdout);
+ fgets (buff, len, stdin);
+}
+
+inline void x11_update_status (X11Plugin *x11,
+ const gchar *s,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ gchar status[20];
+ gint x = 0;
+
+ while (x < x11->win_width) {
+ XPutImage (x11->dpy, x11->win_buf, x11->buf_gc, x11->statusbar, 0, 0, x, x11->map_size->num_rows * TILE_SIZE, 96,
+ 32);
+ x = x + 96;
+ }
+
+ XDrawString (x11->dpy, x11->win_buf, x11->gc, 3, x11->map_size->num_rows * TILE_SIZE + 16, s, strlen (s));
+
+ if (energy > -1) {
+ g_sprintf (status, "Robot Energy: %3d", energy);
+ XDrawString (x11->dpy, x11->win_buf, x11->gc, 240, x11->map_size->num_rows * TILE_SIZE + 12, status,
+ strlen (status));
+ }
+
+ if (score > -1) {
+ g_sprintf (status, "Robot Score: %3d", score);
+ XDrawString (x11->dpy, x11->win_buf, x11->gc, 240, x11->map_size->num_rows * TILE_SIZE + 25, status,
+ strlen (status));
+ }
+
+ if (shields > -1) {
+ g_sprintf (status, "Robot Shields: %3d", shields);
+ XDrawString (x11->dpy, x11->win_buf, x11->gc, 480, x11->map_size->num_rows * TILE_SIZE + 12, status,
+ strlen (status));
+ }
+}
+
+inline void x11_plugin_update_status (X11Plugin *x11,
+ const gchar *s,
+ glong energy,
+ glong score,
+ glong shields)
+{
+ gint x;
+ XEvent ev;
+
+ x11_update_status (x11, s, energy, score, shields);
+
+ while (XPending (x11->dpy)) {
+ XNextEvent (x11->dpy, &ev);
+
+ switch (ev.type) {
+ case KeyPress:
+ case KeyRelease:
+ switch (XKeycodeToKeysym (x11->dpy, ev.xkey.keycode, 0)) {
+ case XK_Escape:
+ exit (0);
+ break;
+ }
+ }
+ }
+
+ put_winbuf (x11);
+}
+
+#ifdef USE_MITSHM
+inline gint
+shm_error_handler (X11Plugin *x11, Display * d, XErrorEvent * e)
+{
+ x11->use_mitshm = 0;
+ return 0;
+}
+#endif
+
+static void
+setup_winbuf (X11Plugin *x11)
+{
+ gint major, minor;
+ Bool shared;
+ XVisualInfo *matches;
+ XVisualInfo plate;
+ gint count;
+ guint depth;
+ XGCValues values;
+ Visual *vis;
+
+ vis = DefaultVisualOfScreen (DefaultScreenOfDisplay (x11->dpy));
+ plate.visualid = XVisualIDFromVisual (vis);
+ matches = XGetVisualInfo (x11->dpy, VisualIDMask, &plate, &count);
+ depth = matches[0].depth;
+
+#ifdef USE_MITSHM
+ x11->use_mitshm = 1;
+ x11->shm_info.shmid = shmget (IPC_PRIVATE, win_height * win_width * depth,
+ IPC_CREAT | 0777);
+ if (x11->shm_info.shmid < 0) {
+ g_fprintf (stderr, "shmget failed, looks like I'll have to use XPutImage\n");
+ x11->use_mitshm = 0;
+ } else {
+ x11->shm_info.shmaddr = (gchar *) shmat (x11->shm_info.shmid, 0, 0);
+
+ if (!x11->shm_info.shmaddr) {
+ g_fprintf (stderr, "shmat failed, looks like I'll have to use XPutImage\n");
+ shmctl (x11->shm_info.shmid, IPC_RMID, 0);
+ use_mitshm = 0;
+ } else {
+ XErrorHandler error_handler = XSetErrorHandler (shm_error_handler);
+
+ x11->win_bufi = XShmCreateImage (x11->dpy, vis, depth, ZPixmap, x11->shm_info.shmaddr,
+ &x11->shm_info, x11->win_width, x11->win_height);
+ x11->shm_info.readOnly = False;
+ XShmAttach (x11->dpy, &x11->shm_info);
+ win_buf = XShmCreatePixmap (x11->dpy, x11->x_win, x11->shm_info.shmaddr, &x11->shm_info,
+ x11->win_width, x11->win_height, depth);
+ XSync (x11->dpy, False);
+ (void) XSetErrorHandler (error_handler);
+ if (!use_mitshm) {
+ p_fprintf (stderr,
+ "XShmAttach failed, looks like I'll have to use XPutImage\n");
+ XFreePixmap (x11->dpy, x11->win_buf);
+ XDestroyImage (x11->win_bufi);
+ shmdt (x11->shm_info.shmaddr);
+ shmctl (x11->shm_info.shmid, IPC_RMID, 0);
+ }
+ }
+ }
+
+ if (!x11->use_mitshm) {
+#endif /* USE_MITSHM */
+ x11->win_buf = XCreatePixmap (x11->dpy, x11->x_win, x11->win_width, x11->win_height, depth);
+#ifdef USE_MITSHM
+ } else {
+ g_printf ("Using MIT Shared Memory Pixmaps. Good.\n", major, minor);
+ }
+#endif
+
+ values.font = x11->text;
+ values.foreground = WhitePixel (x11->dpy, DefaultScreen (x11->dpy));
+
+ x11->buf_gc = XCreateGC (x11->dpy, x11->win_buf, GCFont | GCForeground, &values);
+}
+
+void
+create_image (X11Plugin *x11, gchar **data, XImage ** image)
+{
+ XpmAttributes a;
+ gint err;
+
+ a.valuemask = XpmCloseness | XpmAllocCloseColors;
+ a.closeness = 40000; /* the xpm manual suggests 40000 */
+ a.alloc_close_colors = 1; /* allocate the colours chosen */
+ err = XpmCreateImageFromData (x11->dpy, data, image, NULL, &a);
+ if (err != 0) {
+ g_fprintf (stderr, "Cannot create image from xpm: %s\n",
+ XpmGetErrorString (err));
+ exit (1);
+ }
+}
+
+static void
+put_tile (X11Plugin *x11, XImage *image, gint x, gint y)
+{
+ XPutImage (x11->dpy, x11->win_buf, x11->gc, image, 0, 0, x, y, TILE_SIZE, TILE_SIZE);
+}
+
+static void put_winbuf (X11Plugin *x11)
+{
+#ifdef USE_MITSHM
+ if (use_mitshm)
+ XShmPutImage (x11->dpy, x11->x_win, x11->gc, x11->win_bufi, 0, 0, 0, 0, x11->win_width, x11->win_height,
+ False);
+ else
+#endif
+ XCopyArea (x11->dpy, x11->win_buf, x11->x_win, x11->gc, 0, 0, x11->win_width, x11->win_height, 0, 0);
+
+ XSync (x11->dpy, 0);
+}
+
+static void x11_plugin_interface_init (gpointer g_iface, gpointer iface_data)
+{
+ UserInterfaceClass *klass = (UserInterfaceClass *)g_iface;
+
+ klass->user_interface_add_thing = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint thing))
+ x11_plugin_add_thing;
+
+ klass->user_interface_draw = (void (*) (UserInterface *ui)) x11_plugin_draw;
+ klass->user_interface_update_status = (void (*) (UserInterface *ui,
+ const gchar *s,
+ glong energy,
+ glong score,
+ glong shields))
+ x11_plugin_update_status;
+ klass->user_interface_move_robot = (void (*) (UserInterface *ui,
+ gint from_x,
+ gint from_y,
+ gint to_x,
+ gint to_y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields))
+ x11_plugin_move_robot;
+ klass->user_interface_robot_smell = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ glong energy,
+ glong score,
+ glong shields))
+ x11_plugin_robot_smell;
+ klass->user_interface_robot_zap = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ x11_plugin_robot_zap;
+ klass->user_interface_robot_feel = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ x11_plugin_robot_grab;
+ klass->user_interface_robot_grab = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ x11_plugin_robot_grab;
+ klass->user_interface_robot_look = (void (*) (UserInterface *ui,
+ gint x,
+ gint y,
+ gint cdir,
+ gint x_to,
+ gint y_to,
+ glong energy,
+ glong score,
+ glong shields))
+ x11_plugin_robot_look;
+ klass->user_interface_get_string = (void (*) (UserInterface *ui,
+ gchar *prompt,
+ gchar *buff,
+ gint len))
+ x11_plugin_get_string;
+}
diff --git a/lib/x11plugin.h b/lib/x11plugin.h
new file mode 100644
index 0000000..0c39fa2
--- /dev/null
+++ b/lib/x11plugin.h
@@ -0,0 +1,102 @@
+/* $Id: x11plugin.h,v 1.1 2004/10/21 19:24:30 zeenix Exp $ */
+
+/* GNU Robots game engine. */
+
+/* Copyright (C) 1998 Jim Hall, jhall1@isd.net */
+
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __X11_PLUGIN_H__
+#define __X11_PLUGIN_H__
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/xpm.h>
+#include <X11/keysym.h>
+
+#include <glib-object.h>
+#include "userinterface.h"
+#include "map.h"
+
+G_BEGIN_DECLS
+
+extern GType _x11_plugin_type;
+
+typedef struct _X11Plugin X11Plugin;
+
+struct _X11Plugin {
+ GObject object;
+ Map *map;
+ MapSize *map_size;
+ gint errors;
+
+ Display *dpy;
+ Window x_win;
+ GC gc;
+ GC buf_gc;
+ Font text;
+
+#ifdef USE_MITSHM
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/extensions/XShm.h>
+
+ XShmSegmentInfo
+ shm_info;
+ guchar use_mitshm = 1;
+#endif
+
+ gint win_width;
+ gint win_height;
+
+ Pixmap win_buf;
+
+ XImage *win_bufi;
+ XImage *statusbar;
+ XImage *space;
+ XImage *food;
+ XImage *wall;
+ XImage *prize;
+ XImage *baddie;
+ XImage *robotDirs[4];
+ XImage *robotPix;
+};
+
+typedef struct _X11PluginClass X11PluginClass;
+
+struct _X11PluginClass {
+ GObjectClass parent_class;
+};
+
+#define G_TYPE_X11_PLUGIN (_x11_plugin_type)
+#define G_IS_X11_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_X11_PLUGIN))
+#define G_IS_X11_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_X11_PLUGIN))
+#define X11_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_X11_PLUGIN, X11PluginClass))
+#define X11_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_X11_PLUGIN, X11Plugin))
+#define X11_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_X11_PLUGIN, X11PluginClass))
+
+/* normal GObject stuff */
+GType x11_plugin_get_type (void);
+
+X11Plugin* x11_plugin_new (void);
+
+/* SYMBOLIC CONSTANTS */
+#define dist(f_x, f_y, t_x, t_y) (abs((f_x)-(t_x))+abs((f_y)-(t_y)))
+
+G_END_DECLS
+
+#endif /* __X11_PLUGIN_H__*/
diff --git a/lib/xpm/Makefile.am b/lib/xpm/Makefile.am
new file mode 100644
index 0000000..60cb556
--- /dev/null
+++ b/lib/xpm/Makefile.am
@@ -0,0 +1,31 @@
+##
+## xpm/Makefile.am
+##
+## GNU Robots is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## GNU Robots is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with GNU Robots; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+
+EXTRA_DIST =\
+ baddie.xpm\
+ food.xpm\
+ prize.xpm\
+ robot_east.xpm\
+ robot_north.xpm\
+ robot_south.xpm\
+ robot_west.xpm\
+ robot.xpm\
+ space.xpm\
+ statusbar.xpm\
+ wall.xpm
+
diff --git a/lib/xpm/baddie.xpm b/lib/xpm/baddie.xpm
new file mode 100644
index 0000000..60c1c6d
--- /dev/null
+++ b/lib/xpm/baddie.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char *baddie_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 16 5 1",
+/* colors */
+". c #ffffff",
+"# c #990033",
+"a c #c0c0c0",
+"b c #808080",
+"c c #ffffff",
+/* pixels */
+"................",
+"................",
+"......#...#.....",
+".......###......",
+".....a#####a....",
+".....b#c###b....",
+"....b#c###b#b...",
+"....##cbab###...",
+"...#####a#####..",
+"....####a####...",
+"...#b###a###b#..",
+".....###a###....",
+"....#a##a##a#...",
+".......#b#......",
+"................",
+"................"
+};
diff --git a/lib/xpm/food.xpm b/lib/xpm/food.xpm
new file mode 100644
index 0000000..34558d3
--- /dev/null
+++ b/lib/xpm/food.xpm
@@ -0,0 +1,27 @@
+/* XPM */
+static char *food_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 16 4 1",
+/* colors */
+". c #f83000",
+"# c #c8ccc8",
+"a c #989898",
+"b c #f8fcf8",
+/* pixels */
+"bbbbbbbbbbbbbbbb",
+"bbbbbbbbbbbbbbbb",
+"bbbbbbbbbbbbbbbb",
+"bbb#bbbbbb#b#abb",
+"bbbbbbbbbbbbbabb",
+"bbbbbbbbbbbbbabb",
+"bbbbbbbb.bbbbabb",
+"bbbbbbbb.bbbbabb",
+"bbbbbb.....bbabb",
+"bbbbbbbb.bbbbabb",
+"bbbbbbbb.bbbbabb",
+"bbbbbbbbbbbbbabb",
+"bbbbbbbbbbbbbabb",
+"bbbaaaaaaaaaaabb",
+"bbbbbbbbbbbbbbbb",
+"bbbbbbbbbbbbbbbb"
+};
diff --git a/lib/xpm/prize.xpm b/lib/xpm/prize.xpm
new file mode 100644
index 0000000..96c4dad
--- /dev/null
+++ b/lib/xpm/prize.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static char *prize_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 16 8 1",
+/* colors */
+". c #303098",
+"# c #003098",
+"a c #989898",
+"b c #c8ccc8",
+"c c #606460",
+"d c #f8fcf8",
+"e c #989800",
+"f c #000000",
+/* pixels */
+"dddddddddddddddd",
+"dddddddddddddddd",
+"dddddddddddddddd",
+"dddddddddddddddd",
+"dddd........dddd",
+"dddd#deeeed.dddd",
+"dddd#dedded#dddd",
+"dddd#dedddd#dddd",
+"dddd##.#.###dddd",
+"dddd##c#cc##dddd",
+"dddd##c#cc#.dddd",
+"dddd.#cccc#.dddd",
+"dddddddddddddddd",
+"dddddddddddddddd",
+"dddddddddddddddd",
+"dddddddddddddddd"
+};
diff --git a/lib/xpm/robot.xpm b/lib/xpm/robot.xpm
new file mode 100644
index 0000000..fea60e2
--- /dev/null
+++ b/lib/xpm/robot.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char *robot_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 16 5 1",
+/* colors */
+". c #bfbfbf",
+"# c #000000",
+"a c #808080",
+"b c #c0c0c0",
+"c c #ffffff",
+/* pixels */
+"................",
+"................",
+"................",
+"..####...####...",
+".#bccb#.#bccb#..",
+"#bccccb#bccccb#.",
+"#cccccc#cccccc#a",
+"#cc##cc#cc##cc#a",
+"#cc##cc#cc##cc#a",
+"#bccccb#bccccb#a",
+".#bccb#a#bccb#aa",
+"..####aa.####aa.",
+"...aaaa...aaaa..",
+"................",
+"................",
+"................"
+};
diff --git a/lib/xpm/robot_east.xpm b/lib/xpm/robot_east.xpm
new file mode 100644
index 0000000..14da711
--- /dev/null
+++ b/lib/xpm/robot_east.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char *robot_east_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 16 5 1",
+/* colors */
+". c #bfbfbf",
+"# c #000000",
+"a c #808080",
+"b c #c0c0c0",
+"c c #ffffff",
+/* pixels */
+"................",
+"................",
+"................",
+"..####...####...",
+".#bccb#.#bccb#..",
+"#bccccb#bccccb#.",
+"#cccccc#cccccc#a",
+"#ccc##c#ccc##c#a",
+"#ccc##c#ccc##c#a",
+"#bccccb#bccccb#a",
+".#bccb#a#bccb#aa",
+"..####aa.####aa.",
+"...aaaa...aaaa..",
+"................",
+"................",
+"................"
+};
diff --git a/lib/xpm/robot_north.xpm b/lib/xpm/robot_north.xpm
new file mode 100644
index 0000000..ec7284d
--- /dev/null
+++ b/lib/xpm/robot_north.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char *robot_north_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 16 5 1",
+/* colors */
+". c #bfbfbf",
+"# c #000000",
+"a c #808080",
+"b c #c0c0c0",
+"c c #ffffff",
+/* pixels */
+"................",
+"................",
+"................",
+"..####...####...",
+".#bccb#.#bccb#..",
+"#bc##cb#bc##cb#.",
+"#cc##cc#cc##cc#a",
+"#cccccc#cccccc#a",
+"#cccccc#cccccc#a",
+"#bccccb#bccccb#a",
+".#bccb#a#bccb#aa",
+"..####aa.####aa.",
+"...aaaa...aaaa..",
+"................",
+"................",
+"................"
+};
diff --git a/lib/xpm/robot_south.xpm b/lib/xpm/robot_south.xpm
new file mode 100644
index 0000000..b0ffc68
--- /dev/null
+++ b/lib/xpm/robot_south.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char *robot_south_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 16 5 1",
+/* colors */
+". c #bfbfbf",
+"# c #000000",
+"a c #808080",
+"b c #c0c0c0",
+"c c #ffffff",
+/* pixels */
+"................",
+"................",
+"................",
+"..####...####...",
+".#bccb#.#bccb#..",
+"#bccccb#bccccb#.",
+"#cccccc#cccccc#a",
+"#cccccc#cccccc#a",
+"#cc##cc#cc##cc#a",
+"#bc##cb#bc##cb#a",
+".#bccb#a#bccb#aa",
+"..####aa.####aa.",
+"...aaaa...aaaa..",
+"................",
+"................",
+"................"
+};
diff --git a/lib/xpm/robot_west.xpm b/lib/xpm/robot_west.xpm
new file mode 100644
index 0000000..4a5a2af
--- /dev/null
+++ b/lib/xpm/robot_west.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char *robot_west_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 16 5 1",
+/* colors */
+". c #bfbfbf",
+"# c #000000",
+"a c #808080",
+"b c #c0c0c0",
+"c c #ffffff",
+/* pixels */
+"................",
+"................",
+"................",
+"..####...####...",
+".#bccb#.#bccb#..",
+"#bccccb#bccccb#.",
+"#cccccc#cccccc#a",
+"#c##ccc#c##ccc#a",
+"#c##ccc#c##ccc#a",
+"#bccccb#bccccb#a",
+".#bccb#a#bccb#aa",
+"..####aa.####aa.",
+"...aaaa...aaaa..",
+"................",
+"................",
+"................"
+};
diff --git a/lib/xpm/space.xpm b/lib/xpm/space.xpm
new file mode 100644
index 0000000..bce27fb
--- /dev/null
+++ b/lib/xpm/space.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static char *space_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 16 3 1",
+/* colors */
+". c #989898",
+"# c #c8ccc8",
+"a c #f8fcf8",
+/* pixels */
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaa"
+};
diff --git a/lib/xpm/statusbar.xpm b/lib/xpm/statusbar.xpm
new file mode 100644
index 0000000..89f5a05
--- /dev/null
+++ b/lib/xpm/statusbar.xpm
@@ -0,0 +1,58 @@
+/* XPM */
+static char * statusbar_xpm[] = {
+"96 32 23 1",
+" c None",
+". c #323232",
+"+ c #343434",
+"@ c #363636",
+"# c #313131",
+"$ c #373737",
+"% c #3A3A3A",
+"& c #393939",
+"* c #2F2F2F",
+"= c #262626",
+"- c #282828",
+"; c #2A2A2A",
+"> c #2D2D2D",
+", c #1B1B1B",
+"' c #1D1D1D",
+") c #222222",
+"! c #242424",
+"~ c #202020",
+"{ c #2B2B2B",
+"] c #3D3D3D",
+"^ c #3C3C3C",
+"/ c #3F3F3F",
+"( c #191919",
+".++@@++.##.$%&*=-;>#..>-,')!=)','~=>#*>;-;{>>*>*#......#=;*$&${~)!-;>>>>**#+++*{{>*#.++..+@&&&$@",
+"++@@@.#**>#@&&#{-->*+.>>'~)!!~',''=>##>{-;{>>***##..++..;{*@&@>=!!-{>>>>>**.@+#>>>>#...+#.@$$$$@",
+"++@@+#>>>{>+&&+*--{>.+.*!!!!)~''''!{*#*>;;{>>*#....+@++@>>>#@+*;!=;{>>>>>>*#@@+#{>>*##..#.+@@@@+",
+"+@@@.*{---{#@&$+;-;>#+++;;-=)~''''!;*#*>{{{>>#.+..++@$$$*>{>*#>{=-;>>>>>>>>*.$@@{>>>>##.##...+.+",
+".@@@+*;===;>.@&${;;{*.@@>>{-=)~~'~);>###>>>>>#.@..++@$&&.>;-{>{-=-{>>*>>>{;>#+@@>{{>>>*#***####.",
+"#.@$+>;!!=-;>.@&*>-->#+@##*>{-!)~~)->#..*>>>>#+@++++@$&&@#;=-;-!!-{>**>>{;=-{*.+{{{;{>*#**>>>*##",
+"*.@@@*{====-{>+$.>;-;>#..++.#>-!))!->*#.##>>>#+$+++@@@$&%+>;--!)!={>##*>{-))=>*#>{;-;>>**>>>>>**",
+">#@$@#{-====->.$@#;!->*#.+@$.>;!!!!=>*...#>>>*+$+@++@$$&]$#{;-!~)={>##**{=~~);>>{{;-;{>**>>{{>>*",
+";>+&&.>;)-;;-;>.+.#>;;>*##.$%&#;!!)={>##+..*>>.+++$+..&%$&&.;!!!=={*..*>{-)''~!;=-;=!!{*#*>>>>>*",
+"-{*+&@*{!={;;;>#+.#>{;>*#**@&&+>-=!={>*#...#>*#.+@@+.#@&&&&+>=!==-;>.+#*{;!~')!-=;;-!!;>.#*>>>**",
+"{;;*@&+>=-;;;{>*++.*{{{>**>.$&@.{;--{>>>.+.#**#.+@@+#*#.&^^&*;--;;{>#+++>;=)~~!=-;{;!)-{####*###",
+">=!;+%$.=-;;{{>*.++#>{>>>>>*+&&&>{{;>>>>.++.***#@@@+#*>>&^]%@>;-{{{>#@@${;=!))!!-{>;!!!;##....##",
+">-~-.&&+;;-;{>>>#.++#>>{>>>>#@&&+#>>>>>>..++####+@@@.*{=@&/]&#{;>>{>#++@;;-=!!)!=;>;=)!-*#++@++.",
+">-)-*@$@{;-;>>>>*.@@.*>>{{{>*+$&@+#*>*>>#.+@.##.++@@@#;!*$]/&.>{>>>>#.#*=-==!!!)!-{{=!!->#+@$@+#",
+">{;;>#@@>;-->>>{>#@$@#>>;{>>*#@$&@.#***>>.+@+.#.+++$&.>!-#%/%+>{>>>*#*>;!!====))~={{-==;>*+$&@+#",
+"#>>{{>.+>;=;>>>{>*@&@.*>>{>>>*.@%&+.##*>>#+@+.....@&&+>!!>&]%@>>>>>##>;=))====!)'!;{-=-;>>+$&@.#",
+"=-;>*#**{{-;>>>{>>*+&&.{{{{{>*#+@@$$@+#*>>*+$$+.##+$&&#;=;>+&$.>>>*#.*-~''~=;-!~'~!=--;-{>#@&&@.",
+"-=-{#..*>{;;>>>>{;>.$&.>{{{{>*#.@$$$$@..>>*.@$@...+&%&+>-;>.@@.>*>>*.#{!''~=--=~~~)!--;;{>*+&&$+",
+"{=!;#$@.>{;{>**>;-{*$$+#>>>>>>**@@$&$$$@>>*.@$$@.#.$%%$.;;>#.+#**{->+@>=''')-;-=~)!=--;->>*+&&&$",
+">=~-#&&+>>{{>*##--->.$@.>>>>>>>*+@$&&&&&##*#+@$@.##+&&&+{{>*#.#**;)-#@#;''')=;;-)!!=--;;{>>#@&&$",
+">-)=*$&&*>>>*#.#;-!;*++.*>>>>>>>.+@$&&%%+.*#.@$$.*>*+$@.>>>*##*>>!'!>.#>~'''!-;{===--;;;>>{>.$$&",
+">;==>.$&+*>>*...>;!={*##>*>>>>>>#.+@$&&%&+#*#+$&+*>>*.#**>*#.#>;=~''=>**!)'')-;;;;-;;;{{*>{{>.++",
+">>{-->@^@.*>#...#{=!->*>>>>>>>>>##.+@&&%&$#**+$$&.>{>**>**.++#{-''','!>.;)''~=-{{{{;{{>>*>;-{>*#",
+">>>;!>+^$+***.+.+>=)={>>>>>>***>**#.@$&&^&#**.@&%@>{>>>>*#+$@#{!(,'(('{.{=~''!-;>>{{{{>>.>-=-{>>",
+">>>{;>*.@+####.@.#>=~~->;{>>>*>*>>*#.+$&&&@#>>#@$$.>{{>*+##+&$*-,'''(')-;-!)');>*>>>>>*##*{-=-;>",
+">>>{{{>#++.####.+.#;!)->{>>>>**>>>**.+@$&&$#>{>+&$+#>>*..##+&$#{''~','~=-;=)~!->>*>****#.*>-=-;{",
+">>>>{{>*++..***>+@+>-!=;{{>>****>>>*#.++&&$.>;>*$$+#*>#+#**+$&@#)))'''~);;-!))->>*##..+..*>-=-;;",
+">>>>>{{>..+.#*>;+@$.>==-{{>>>*#*>>>>**..$&&+>-;{++.#**#.*>>#$&$@--!)~'~);;;-=!-;>*#+@@@++#>-==-;",
+"{>**>{{{#.++.>-=*+$$#;=={{{>>**#>>>>>**#+$&+>-=->>**>>*#>>>*.$&&>>;=!!))-{>{---;>*.+@$$&@.>;-=-;",
+"{>*#>>{{>#+@.>=~-*$&+>-!;;{{>>*#>>>>>>>**+$@*;==;{>>>>>*>{>>*+$&.*>{;;=!;{>>>{;{>**.@$&&&+*{---;",
+"->*#*>{{>*+@+>!'~;@&@*-=;;;;>>**>>>>>>>>{#@@*;==-;>>>>>#>>{{>*+&$+>>>>{=-{***>{>>>**.$&^&$#>---;",
+"-{*#*>{{;>+@+>!'(-.&$*;=---;{>***>>>>>>>-*+@#{=!-{>>>>*#>{;-;>.$&@#***>{->*.*>>>*>>>#@&]&$.>;-;{"};
diff --git a/lib/xpm/wall.xpm b/lib/xpm/wall.xpm
new file mode 100644
index 0000000..48b6a7c
--- /dev/null
+++ b/lib/xpm/wall.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static char *wall_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 16 16 3 1",
+/* colors */
+". c #cccccc",
+"# c #993300",
+"a c #cc0033",
+/* pixels */
+"...............#",
+".aaaaaaaaaaaaaa#",
+".aaaaaaaaaaaaaa#",
+".aa##########aa#",
+".aa#aaaaaaaa.aa#",
+".aa#aaaaaaaa.aa#",
+".aa#aa...#aa.aa#",
+".aa#aa.aa#aa.aa#",
+".aa#aa.aa#aa.aa#",
+".aa#aa####aa.aa#",
+".aa#aaaaaaaa.aa#",
+".aa#aaaaaaaa.aa#",
+".aa#.........aa#",
+".aaaaaaaaaaaaaa#",
+".aaaaaaaaaaaaaa#",
+"################"
+};