From e6e7222d5a730368ed4e84c2e0f55427460e5230 Mon Sep 17 00:00:00 2001 From: Bradley Smith Date: Mon, 21 Jan 2008 00:16:45 +0000 Subject: Imported GNU robots from CVS. Signed-off-by: Bradley Smith --- src/map.c | 297 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 src/map.c (limited to 'src/map.c') diff --git a/src/map.c b/src/map.c new file mode 100644 index 0000000..bae21dc --- /dev/null +++ b/src/map.c @@ -0,0 +1,297 @@ +/* GNU Robots. */ + +/* 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 /* for getopt */ +#include +#include /* for strdup */ + +#include + +#include "configs.h" +#include "map.h" + +enum +{ + ARG_0, + ARG_SIZE +}; + +GType _map_type = 0; + +static void map_class_init (MapClass * klass); +static void map_init (GObject * object); + +static void map_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); + +static void map_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GObjectClass *parent_class = NULL; + +GType +map_get_type (void) +{ + if (!_map_type) { + static const GTypeInfo object_info = { + sizeof (MapClass), + NULL, + NULL, + (GClassInitFunc) map_class_init, + NULL, + NULL, + sizeof (Map), + 0, + (GInstanceInitFunc) map_init, + NULL + }; + + _map_type = + g_type_register_static (G_TYPE_OBJECT, + "Map", + &object_info, + 0); + } + + return _map_type; +} + +static void +map_class_init (MapClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + parent_class = g_type_class_ref (G_TYPE_OBJECT); + + gobject_class->set_property = map_set_property; + gobject_class->get_property = map_get_property; + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZE, + g_param_spec_pointer ("size", + "Size", + "The size of the map", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +map_init (GObject * object) +{ + Map *map = MAP (object); + + map->_map = NULL; + map->size.num_rows = -1; + map->size.num_cols = -1; +} + +/* fload_map - loads a map file into memory. */ +static void +fload_map (Map *map, FILE * stream) +{ + gint ch; + gint i, j; + + /* Read the map file */ + i = 0; + j = 0; + + while ((ch = fgetc (stream)) != EOF) { + /* Add the ch to the map */ + + switch (ch) { + case SPACE: + case WALL: + case BADDIE: + case PRIZE: + case FOOD: + map->_map[j][i] = ch; + break; + + case '\n': + /* ignore the newline */ + break; + + default: + /* not a valid map char, but we'll add a space anyway */ + + map->_map[j][i] = SPACE; + break; + } /* switch */ + + /* Check for newline */ + + if (ch == '\n') { + /* the line may have ended early. pad with WALL */ + + while (i < map->size.num_cols) { + map->_map[j][i++] = WALL; + } + } + + + /* if newline */ + /* Check for limits on map */ + if (++i >= map->size.num_cols) { + /* We have filled this line */ + + ++j; + i = 0; + + /* Flush the buffer for this line */ + + while (ch != '\n') { + ch = fgetc (stream); + } + } + /* if i */ + if (j >= map->size.num_rows) { + /* the map is filled */ + + return; + } + } /* while fgetc */ + + /* After the loop, we are done reading the map file. Make sure this + is bounded by WALL. */ + if (i > 0) { + ++j; + } + + for (i = 0; i < map->size.num_cols; i++) { + map->_map[j][i] = WALL; + } +} + +static void +cleanup_map (Map *map) +{ + gint i, j; + + /* make sure there is a wall at top/bottom */ + + for (i = 0; i < map->size.num_cols; i++) { + map->_map[0][i] = WALL; + map->_map[map->size.num_rows - 1][i] = WALL; + } + + /* make sure there is a wall at left/right */ + + for (j = 0; j < map->size.num_rows; j++) { + map->_map[j][0] = WALL; + map->_map[j][map->size.num_cols - 1] = WALL; + } +} + +static void +map_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + Map *map; + guint i; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (G_IS_MAP (object)); + + map = MAP (object); + + switch (prop_id) { + case ARG_SIZE: + /* Free the map if any */ + if (map->_map != NULL) { + for (i = 0; i < map->size.num_rows; i++) { + g_free (map->_map[i]); + } + + g_free (map->_map); + } + + /* Get the new size of the map */ + g_memmove (&map->size, g_value_get_pointer (value), sizeof (MapSize)); + + /* Allocate the according to the new size */ + map->_map = g_malloc (map->size.num_rows * sizeof (gint **)); + + for (i = 0; i < map->size.num_rows; i++) { + map->_map[i] = g_malloc (map->size.num_cols * sizeof (gint)); + } + + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +map_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + Map *map; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (G_IS_MAP (object)); + + map = MAP (object); + + switch (prop_id) { + case ARG_SIZE: + g_value_set_pointer (value, g_memdup (&map->size, sizeof (MapSize))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +Map * +map_new_from_file (const gchar *map_file, gint num_rows, gint num_cols) +{ + GObject *object; + Map *map; + gint **buf; + guint i; + FILE *stream; + MapSize size; + + size.num_rows = num_rows; + size.num_cols = num_cols; + + stream = fopen (map_file, "r"); + + if (stream != NULL) { + map = MAP (g_object_new (map_get_type (), + "size", &size, + NULL)); + fload_map (map, stream); + fclose (stream); + cleanup_map (map); + + return map; + } + + /* else, no file to open */ + else { + g_warning ("Could not open map file: %s\n", map_file); + return NULL; + } +} + -- cgit v1.1