home · contact · privacy
Re-wrote map object system to use same structs for items and monsters, and switched...
authorChristian Heller <c.heller@plomlompom.de>
Mon, 23 Sep 2013 01:55:49 +0000 (03:55 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Mon, 23 Sep 2013 01:55:49 +0000 (03:55 +0200)
13 files changed:
src/draw_wins.c
src/draw_wins.h
src/main.c
src/main.h
src/map_object_actions.c
src/map_object_actions.h
src/map_objects.c
src/map_objects.h
src/misc.c
src/misc.h
src/readwrite.c
src/readwrite.h
src/rexit.c

index 53ce68da0a4691846bc86e46b77251562c33f5c0..2b04ff4e93f6f2a6c4a7e8915e284305f9fe20b6 100644 (file)
@@ -8,7 +8,7 @@
 #include "windows.h"     /* for structs Win, Frame, for draw_scroll_hint() */
 #include "misc.h"        /* for center_offset(), try_malloc() */
 #include "keybindings.h" /* for struct KeyBinding, for get_name_to_keycode() */
-#include "map_objects.h" /* for structs MapObj, Player */
+#include "map_objects.h" /* for structs MapObj, Player, get_map_object_def() */
 #include "map.h"         /* for Map struct */
 #include "main.h"        /* for World struct */
 #include "rexit.h"       /* for err_exit() */
@@ -195,12 +195,12 @@ static void draw_map_objects(struct World * world, struct MapObj * start,
     for (o = start; o != 0; o = o->next)
     {
         if (   o->pos.y >= map->offset.y
-            && o->pos.y < map->offset.y + win->frame.size.y
+            && o->pos.y <  map->offset.y + win->frame.size.y
             && o->pos.x >= map->offset.x
-            && o->pos.x < map->offset.x + win->frame.size.x)
+            && o->pos.x <  map->offset.x + win->frame.size.x)
         {
-            d = get_map_obj_def (world, o->type);
-            c = d->mapchar;
+            d = get_map_object_def(world, o->type);
+            c = d->char_on_map;
             mvwaddch(win->frame.curses_win,
                      o->pos.y - map->offset.y, o->pos.x - map->offset.x, c);
         }
@@ -341,12 +341,11 @@ extern void draw_win_map(struct Win * win)
             }
         }
     }
-    draw_map_objects (world, (struct MapObj *) world->item, map, win);
-    draw_map_objects (world, (struct MapObj *) world->monster, map, win);
+    draw_map_objects(world, world->map_objs, map, win);
     if (   player->pos.y >= map->offset.y
-        && player->pos.y < map->offset.y + win->frame.size.y
+        && player->pos.y <  map->offset.y + win->frame.size.y
         && player->pos.x >= map->offset.x
-        && player->pos.x < map->offset.x + win->frame.size.x)
+        && player->pos.x <  map->offset.x + win->frame.size.x)
     {
         mvwaddch(win->frame.curses_win,
                  player->pos.y - map->offset.y, player->pos.x - map->offset.x,
index c86f367dc6dc5d16461751b1122cb7082c604bf3..3ebdf76acbeab30c007051ab9a088af9db1b91af 100644 (file)
@@ -23,6 +23,8 @@ extern void draw_win_keybindings_global(struct Win * win);
 extern void draw_win_keybindings_winconf_geometry(struct Win * win);
 extern void draw_win_keybindings_winconf_keybindings(struct Win * win);
 
+
+
 /* Routines to draw windows' configuration views. */
 extern void draw_winconf_keybindings(struct Win * win);
 extern void draw_winconf_geometry(struct Win * win);
index 8d00a5df769bf6c76b3e6b8dba7ead74371143d7..fcaac80e3556d1b6e0912775a67f7ddfd4f563cc 100644 (file)
@@ -6,20 +6,19 @@
 #include <ncurses.h> /* for initscr(), noecho(), curs_set(), keypad(), raw() */
 #include <time.h> /* for time() */
 #include <unistd.h> /* for getopt(), optarg */
-#include <stdint.h> /* for uint16_t, uint32_t */
+#include <stdint.h> /* for uint32_t */
 #include "windows.h" /* for structs WinMeta, Win, init_win_meta(), draw_all_wins()
                       */
-#include "readwrite.h" /* for [read/write]_uint[8/16/32][_bigendian](),
+#include "readwrite.h" /* for read_uint32_bigendian](), write_uint32_bigendian(),
                         * try_fopen(), try_fclose(), try_fclose_unlink_rename()
                         */
-#include "map_objects.h" /* for structs Monster, Item, Player,
-                          * init_map_object_defs(), read_map_objects(),
+#include "map_objects.h" /* for structs MapObj Player, init_map_object_defs(),
                           * build_map_objects()
                           */
 #include "map.h" /* for struct Map, init_map() */
 #include "misc.h" /* for update_log(), find_passable_pos(), save_game(),
                    * try_calloc(), check_tempfile(), check_xor_files(),
-                   * load_interface_conf()
+                   * load_interface_conf(), load_game()
                    */
 #include "wincontrol.h" /* get_win_by_id(), get_winconf_by_win() */
 #include "rrand.h" /* for rrand(), rrand_seed() */
@@ -85,11 +84,9 @@ int main(int argc, char *argv[])
     struct Player player;
     player.hitpoints = 5;
     world.player = &player;
-    world.monster = 0;
-    world.item = 0;
-    init_map_object_defs(&world, "config/defs");
+    init_map_object_defs(&world, "config/defs2");
     set_cleanup_flag(CLEANUP_MAP_OBJECT_DEFS);
-    world.map_object_count = 1;
+    world.map_obj_count = 1;
 
     /* For interactive mode, try to load world state from savefile. */
     char * err_r = "Trouble loading game (in main()) / "
@@ -97,22 +94,8 @@ int main(int argc, char *argv[])
     FILE * file;
     if (1 == world.interactive && 0 == access(savefile, F_OK))
     {
-        file = try_fopen(savefile, "r", &world, f_name);
-        if (   read_uint32_bigendian(file, &world.seed)
-            || read_uint32_bigendian(file, &world.turn)
-            || read_uint16_bigendian(file, &world.score)
-            || read_uint16_bigendian(file, &player.pos.y)
-            || read_uint16_bigendian(file, &player.pos.x)
-            || read_uint8(file, &player.hitpoints)
-            || read_map_objects(&world, &world.monster, file)
-            || read_map_objects(&world, &world.item,    file))
-        {
-            exit_err(1, &world, err_r);
-        }
+        load_game(&world);
         set_cleanup_flag(CLEANUP_MAP_OBJECTS);
-        try_fclose(file, &world, f_name);
-        player.pos.y--;
-        player.pos.x--;
     }
 
     /* For non-interactive mode, try to load world state from record file. */
@@ -153,12 +136,12 @@ int main(int argc, char *argv[])
     if (0 == world.turn)
     {
         player.pos = find_passable_pos(world.map);
-        void * foo;
-        foo = build_map_objects(&world, &world.monster, 1, 1 + rrand() % 27);
-        foo = build_map_objects(&world, foo, 2, 1 + rrand() % 9);
-        build_map_objects(&world, foo, 3, 1 + rrand() % 3);
-        foo = build_map_objects(&world, &world.item, 4, 1 + rrand() % 3);
-        build_map_objects(&world, foo, 5, 1 + rrand() % 3);
+        struct MapObj ** ptr;
+        ptr = build_map_objects(&world, &world.map_objs, 1, 1 + rrand() % 27);
+        ptr = build_map_objects(&world, ptr, 2, 1 + rrand() % 9);
+        ptr = build_map_objects(&world, ptr, 3, 1 + rrand() % 3);
+        ptr = build_map_objects(&world, ptr, 4, 1 + rrand() % 3);
+        ptr = build_map_objects(&world, ptr, 5, 1 + rrand() % 3);
         set_cleanup_flag(CLEANUP_MAP_OBJECTS);
         world.turn = 1;
     }
index 83bdb83d2aa12717e3c857bacaca8e4c15b1da6f..a2900997a76873ec6a66ab7b87fd2eb8050bb418 100644 (file)
 struct WinMeta;
 struct WinConf;
 struct Win;
-struct KeyBinding;
-struct KeysWinData;
 struct Map;
-struct ItemDef;
-struct MonsterDef;
+struct MapObjDef;
+struct MapObj;
 
 
 
@@ -32,16 +30,14 @@ struct World
     uint16_t score;                   /* Player's score. */
     char * log;                       /* Pointer to the game log string. */
     struct Map * map;                 /* Pointer to the game map cells. */
-    struct ItemDef * item_def;        /* Pointer to the item definitions. */
-    struct Item * item;               /* Pointer to the items' data. */
-    struct MonsterDef * monster_def;  /* Pointer to the monster definitions. */
-    struct Monster * monster;         /* Pointer to the monsters' data. */
-    struct Player * player;           /* Pointer to the player data. */
     struct CommandDB * cmd_db;        /* Pointer to the command database. */
     struct WinMeta * wmeta;           /* Pointer to window manager's WinMeta. */
     struct WinConf * winconfs;        /* Pointer to windows' configurations. */
     char * winconf_ids;               /* Pointer to string of Winconfs' ids. */
-    uint8_t map_object_count;         /* Counts loaded/generated map objects. */
+    struct Player * player;           /* Pointer to the player data. */
+    uint8_t map_obj_count;            /* Counts map objects generated so far. */
+    struct MapObjDef * map_obj_defs;  /* Map object type definitions chain. */
+    struct MapObj * map_objs;         /* Map objects chain. */
 };
 
 
index 1b1433949599d5792cf7f1540bc56347d3b87663..23152e229de5d78476178c20feb3d6e179b68900 100644 (file)
@@ -1,13 +1,14 @@
 /* map_object_actions.c */
 
 #include "map_object_actions.h"
-#include <stdlib.h> /* for free() */
 #include <string.h> /* for strlen() */
 #include "yx_uint16.h" /* for yx_uint16 struct, mv_yx_in_dir(), yx_uint16_cmp */
-#include "misc.h" /* for update_log(), turn_over(), try_malloc() */
+#include "misc.h" /* for update_log(), turn_over() */
 #include "map.h" /* for Map struct */
 #include "main.h" /* for World struct */
-#include "map_objects.h" /* for map object (definition) structs */
+#include "map_objects.h" /* for structs MapObj, MapObjDef,
+                          * get_map_object_def()
+                          */
 #include "rrand.h" /* for rrand() */
 #include "command_db.h" /* for get_command_id() */
 
@@ -15,7 +16,7 @@
 
 /* Log monster (described by "dsc_monster1") bumping into "monster2". */
 static void monster_bumps_monster(struct World * world, char * dsc_monster1,
-                                  struct Monster * monster2);
+                                  struct MapObj * monster2);
 
 /* Decrement player HPs due to attack of monster described by "dsc_monster",
  * kill player if his HP hit zero; log the whole action.
@@ -26,7 +27,7 @@ static void monster_hits_player(struct World * world, char * dsc_monster);
  * corpse and increment player's score by the amount of hitpoints the monster
  * started with; log the whole action.
  */
-static void player_hits_monster(struct World * world, struct Monster * monster);
+static void player_hits_monster(struct World * world, struct MapObj * monster);
 
 /* Try moving the player in direction "d" towards coordinate "target"; log
  * success or failure of the whole action.
@@ -37,12 +38,12 @@ static void try_player_move(struct World * world,
 
 
 static void monster_bumps_monster(struct World * world, char * dsc_monster1,
-                                  struct Monster * monster2)
+                                  struct MapObj * monster2)
 {
     char * bump_dsc = " bumps into ";
-    struct MapObjDef * mod = get_map_obj_def(world, monster2->map_obj.type);
-    char msg[strlen(dsc_monster1) + strlen(bump_dsc) + strlen(mod->desc) + 3];
-    sprintf(msg, "\n%s%s%s.", dsc_monster1, bump_dsc, mod->desc);
+    struct MapObjDef * mod = get_map_object_def(world, monster2->type);
+    char msg[strlen(dsc_monster1) + strlen(bump_dsc) + strlen(mod->name) + 3];
+    sprintf(msg, "\n%s%s%s.", dsc_monster1, bump_dsc, mod->name);
     update_log(world, msg);
 }
 
@@ -55,6 +56,7 @@ static void monster_hits_player(struct World * world, char * dsc_monster)
     sprintf(msg, "\n%s%s.", dsc_monster, hit_dsc);
     update_log(world, msg);
     world->player->hitpoints--;
+
     if (0 == world->player->hitpoints)
     {
         update_log(world, "\nYou are dead.");
@@ -63,45 +65,25 @@ static void monster_hits_player(struct World * world, char * dsc_monster)
 
 
 
-static void player_hits_monster(struct World * world, struct Monster * monster)
+static void player_hits_monster(struct World * world, struct MapObj * monster)
 {
-    char * f_name = "player_hits_monster()";
-    struct MapObjDef * mod = get_map_obj_def(world, monster->map_obj.type);
+    struct MapObjDef * mod = get_map_object_def(world, monster->type);
     char * hit_dsc = "You hit the ";
-    char * monster_dsc = mod->desc;
+    char * monster_dsc = mod->name;
     char hitmsg[strlen(hit_dsc) + strlen(monster_dsc) + 3];
     sprintf(hitmsg, "\n%s%s.", hit_dsc, monster_dsc);
     update_log(world, hitmsg);
-    monster->hitpoints--;
-    if (0 == monster->hitpoints)
+    monster->lifepoints--;
+    if (0 == monster->lifepoints)
     {
         hit_dsc = "You kill the ";
         char kill_msg[strlen(hit_dsc) + strlen(monster_dsc) + 3];
         sprintf(kill_msg, "\n%s%s.", hit_dsc, monster_dsc);
         update_log(world, kill_msg);
-        struct MonsterDef * md = (struct MonsterDef * ) mod;
-        struct Item * corpse = try_malloc(sizeof(struct Item), world, f_name);
-        corpse->map_obj.type = md->corpse_id;
-        corpse->map_obj.pos = monster->map_obj.pos;
-        corpse->map_obj.next = world->item;
-        world->item = corpse;
-        if (world->monster == monster)
-        {
-            world->monster = world->monster->map_obj.next;
-        }
-        else
-        {
-            struct Monster * m_prev;
-            for (m_prev = world->monster;
-                 m_prev->map_obj.next != monster;
-                 m_prev = m_prev->map_obj.next);
-            {
-                m_prev->map_obj.next = monster->map_obj.next;
-            }
-        }
-        uint8_t score = md->hitpoints_start;
+        struct MapObjDef * md = mod;
+        monster->type = md->corpse_id;
+        uint8_t score = md->lifepoints;
         world->score = world->score + score;
-        free(monster);
     }
 }
 
@@ -140,27 +122,27 @@ static void try_player_move(struct World * world,
 
 
 
-extern void move_monster(struct World * world, struct Monster * monster)
+extern void move_monster(struct World * world, struct MapObj * monster)
 {
     char d = rrand() % 5;
-    struct yx_uint16 t = mv_yx_in_dir(d, monster->map_obj.pos);
-    struct MapObjDef * mod = get_map_obj_def(world, monster->map_obj.type);
-    char * dsc = mod->desc;
+    struct yx_uint16 t = mv_yx_in_dir(d, monster->pos);
+    struct MapObjDef * mod = get_map_object_def(world, monster->type);
+    char * dsc = mod->name;
     if (yx_uint16_cmp(&t, &world->player->pos))
     {
         monster_hits_player(world, dsc);
         return;
     }
-    struct Monster * other_monster;
-    for (other_monster = world->monster;
+    struct MapObj * other_monster;
+    for (other_monster = world->map_objs;
          other_monster != 0;
-         other_monster = other_monster->map_obj.next)
+         other_monster = other_monster->next)
     {
-        if (other_monster == monster)
+        if (0 == other_monster->lifepoints || other_monster == monster)
         {
             continue;
         }
-        if (yx_uint16_cmp(&t, &other_monster->map_obj.pos))
+        if (yx_uint16_cmp(&t, &other_monster->pos))
         {
             monster_bumps_monster(world, dsc, other_monster);
             return;
@@ -168,7 +150,7 @@ extern void move_monster(struct World * world, struct Monster * monster)
     }
     if (is_passable(world->map, t))
     {
-        monster->map_obj.pos = t;
+        monster->pos = t;
     }
 }
 
@@ -199,12 +181,12 @@ extern void move_player(struct World * world, enum dir d)
     action_dsc[len + 1] = '\0';
     uint8_t action_id = get_command_id(world, action_dsc);
     struct yx_uint16 t = mv_yx_in_dir(d, world->player->pos);
-    struct Monster * monster;
-    for (monster = world->monster;
+    struct MapObj * monster;
+    for (monster = world->map_objs;
          monster != 0;
-         monster = monster->map_obj.next)
+         monster = monster->next)
     {
-        if (yx_uint16_cmp(&t, &monster->map_obj.pos))
+        if (0 < monster->lifepoints && yx_uint16_cmp(&t, &monster->pos))
         {
             player_hits_monster(world, monster);
             turn_over(world, action_id);
index 6034611a7df36ddc4d0f8851f5278a72329f6b17..ae764b9f1ea746d97fd1c555f9eb003f977e3cf3 100644 (file)
@@ -11,7 +11,7 @@
 #include "yx_uint16.h" /* for yx_uint16 coordinates */
 struct World;
 struct Map;
-struct Monster;
+struct MapObj;
 
 
 
@@ -20,7 +20,7 @@ struct Monster;
  * and thereby potentially trigger the player's death. Update the log for any
  * contact action.
  */
-extern void move_monster(struct World * world, struct Monster * monster);
+extern void move_monster(struct World * world, struct MapObj * monster);
 
 
 
index 485ab6da0031a97146e42eba9c8bb1192a0704b5..e69028122d694d64ea24d5ffd9724541d34ec645 100644 (file)
 
 
 
-/* Return pointer to newly allocated map object struct of size "size". If first
- * in map object chain ("first" pointing to !0), point "start" to it.
- */
-static struct MapObj * get_next_map_obj(struct World * world,
-                                        void * start, uint8_t * first,
-                                        size_t size, struct MapObj * map_obj);
-
-
-
-/* Map-object-type-specific helpers to (build|write|read)_map_objects(). */
-static void build_map_objects_itemdata(struct MapObjDef * map_obj_def,
-                                       void * start);
-static void build_map_objects_monsterdata(struct MapObjDef * map_obj_def,
-                                          void * start);
-static uint8_t write_map_objects_monsterdata(void * start, FILE * file);
-static uint8_t read_map_objects_monsterdata( void * start, FILE * file);
-
-
-
-static struct MapObj * get_next_map_obj(struct World * world,
-                                        void * start, uint8_t * first,
-                                        size_t size, struct MapObj * map_obj)
-{
-    char * f_name = "get_next_map_obj()";
-    if (* first)
-    {
-        struct MapObj * * z = start;
-        map_obj = try_malloc(size, world, f_name);
-        * z = map_obj;
-        * first = 0;
-    }
-    else
-    {
-        map_obj->next = try_malloc(size, world, f_name);
-        map_obj = map_obj->next;
-    }
-    return map_obj;
-}
-
-
-
-static void build_map_objects_itemdata(struct MapObjDef * map_obj_def,
-                                       void * start)
-{
-  struct Item * i = (struct Item *) start;
-  i->map_obj.type = map_obj_def->id;
-}
-
-
-
-static void build_map_objects_monsterdata(struct MapObjDef * map_obj_def,
-                                          void * start)
-{
-    struct Monster * m = (struct Monster *) start;
-    m->map_obj.type = map_obj_def->id;
-    struct MonsterDef * md = (struct MonsterDef *) map_obj_def;
-    m->hitpoints = md->hitpoints_start;
-}
-
-
-
-static uint8_t write_map_objects_monsterdata(void * start, FILE * file)
-{
-    struct Monster * m = (struct Monster *) start;
-    return write_uint8(m->hitpoints, file);
-}
-
-
-
-static uint8_t read_map_objects_monsterdata (void * start, FILE * file)
-{
-    struct Monster * m = (struct Monster *) start;
-    return read_uint8(file, &m->hitpoints);
-}
-
-
-
 extern void init_map_object_defs(struct World * world, char * filename)
 {
     char * f_name = "init_map_object_defs()";
     FILE * file = try_fopen(filename, "r", world, f_name);
     uint16_t linemax = get_linemax(file, world, f_name);
-    struct MapObjDef  mod;
-    struct ItemDef    id;
-    struct MonsterDef md;
-    world->item_def    = 0;
-    world->monster_def = 0;
-    struct ItemDef    * * p_p_id  = &world->item_def;
-    struct MonsterDef * * p_p_md  = &world->monster_def;
-    char defline[linemax + 1];
-    char * line_p;
+    struct MapObjDef ** last_mod_ptr_ptr = &world->map_obj_defs;
     char * delim = " ";
-    while (fgets(defline, linemax + 1, file))
+    char line[linemax + 1];
+    while (try_fgets(line, linemax + 1, file, world, f_name))
     {
-        mod.next    = 0;
-        mod.id      = atoi(strtok(defline, delim));
-        mod.m_or_i  = * strtok(NULL, delim);
-        mod.mapchar = * strtok(NULL, delim);
-        if ('i' == mod.m_or_i)
-        {
-            line_p = strtok(NULL, delim);
-        }
-        else
-        {
-            md.corpse_id       = atoi(strtok(NULL, delim));
-            md.hitpoints_start = atoi(strtok(NULL, delim));
-            line_p             = strtok(NULL, delim);
-        }
-        mod.desc = try_calloc(strlen(line_p), sizeof(char), world, f_name);
-        memcpy(mod.desc, line_p, strlen(line_p) - 1);
-        if ('i' == mod.m_or_i)
-        {
-            id.map_obj_def = mod;
-            * p_p_id       = try_malloc(sizeof(struct ItemDef), world, f_name);
-            * * p_p_id     = id;
-            p_p_id         = (struct ItemDef    * *) * p_p_id;
-        }
-        else
-        {
-            md.map_obj_def = mod;
-            * p_p_md     = try_malloc(sizeof(struct MonsterDef), world, f_name);
-            * * p_p_md     = md;
-            p_p_md         = (struct MonsterDef * *) * p_p_md;
-        }
+        struct MapObjDef * mod;
+        mod = try_malloc(sizeof(struct MapObjDef), world, f_name);
+        mod->next = NULL;
+        mod->id = atoi(strtok(line, delim));
+        mod->corpse_id = atoi(strtok(NULL, delim));
+        mod->char_on_map = * strtok(NULL, delim);
+        mod->lifepoints = atoi(strtok(NULL, delim));
+        char * name = strtok(NULL, "\n");
+        mod->name = try_malloc(strlen(name) + 1, world, f_name);
+        memcpy(mod->name, name, strlen(name) + 1);
+        * last_mod_ptr_ptr = mod;
+        last_mod_ptr_ptr = &mod->next;
     }
     try_fclose(file, world, f_name);
 }
 
 
 
-extern void free_item_defs(struct ItemDef * id_start)
+extern void free_map_object_defs(struct MapObjDef * mod_start)
 {
-    if (0 != id_start->map_obj_def.next)
+    if (NULL == mod_start)
     {
-        free_item_defs((struct ItemDef *) id_start->map_obj_def.next);
-    }
-    free(id_start->map_obj_def.desc);
-    free(id_start);
-}
-
-
-
-
-extern void free_monster_defs(struct MonsterDef * md_start)
-{
-    if (0 != md_start->map_obj_def.next)
-    {
-        free_monster_defs((struct MonsterDef *) md_start->map_obj_def.next);
-    }
-    free(md_start->map_obj_def.desc);
-    free(md_start);
-}
-
-
-
-extern uint8_t write_map_objects(struct World * world, void * start,
-                                 FILE * file)
-{
-    struct MapObj * map_obj;
-    struct MapObjDef * mod;
-    for (map_obj = start; map_obj != 0; map_obj = map_obj->next)
-    {
-        if (   write_uint8(map_obj->type, file)
-            || write_uint8(map_obj->id, file)
-            || write_uint16_bigendian(map_obj->pos.y + 1, file)
-            || write_uint16_bigendian(map_obj->pos.x + 1, file))
-        {
-            return 1;
-        }
-        mod = get_map_obj_def(world, map_obj->type);
-        if ('m' == mod->m_or_i)
-        {
-            if (write_map_objects_monsterdata(map_obj, file))
-            {
-                return 1;
-            }
-        }
+        return;
     }
-    return write_uint16_bigendian(0, file);
+    free_map_object_defs(mod_start->next);
+    free(mod_start->name);
+    free(mod_start);
 }
 
 
 
-extern uint8_t read_map_objects(struct World * world, void * start, FILE * file)
+extern void write_map_objects(struct World * world, FILE * file)
 {
-    char * err = "Trouble in read_map_objects() with get_next_map_obj().";
-    struct MapObj * map_obj;
-    struct MapObjDef * mod;
-    size_t size;
-    uint8_t type;
-    uint8_t first = 1;
-    long pos;
-    uint16_t read_uint16 = 0;
-    while (1)
-    {
-        pos = ftell(file);
-        if (read_uint16_bigendian(file, &read_uint16))
-        {
-            return 1;
-        }
-        if (0 == read_uint16)
-        {
-            break;
-        }
-        fseek(file, pos, SEEK_SET);
-        if (read_uint8(file, &type))
-        {
-            return 1;
-        }
-        mod = get_map_obj_def(world, type);
-        if ('m' == mod->m_or_i)
-        {
-            size = sizeof(struct Monster);
-        }
-        else
-        {
-            size = sizeof(struct Item);
-        }
-        map_obj = get_next_map_obj(world, start, &first, size, map_obj);
-        exit_err(NULL == map_obj, world, err);
-        map_obj->type = type;
-        if (   read_uint8(file, &map_obj->id)
-            || read_uint16_bigendian(file, &map_obj->pos.y)
-            || read_uint16_bigendian(file, &map_obj->pos.x))
-        {
-            return 1;
-        }
-        map_obj->pos.y--;
-        map_obj->pos.x--;
-        if ('m' == mod->m_or_i)
-        {
-            if (read_map_objects_monsterdata(map_obj, file))
-            {
-                return 1;
-            }
-        }
-    }
-    if (!first)
+    char * f_name = "write_map_objects()";
+    struct MapObj * mo = world->map_objs;
+    uint8_t size = 3 + 1 + 3 + 1 + 3 + 1 + 5 + 1 + 5 + 1;
+    char line[size];
+    while (NULL != mo)
     {
-        map_obj->next = 0;
+        sprintf(line, "%d %d %d %d %d\n",
+                mo->id, mo->type, mo->lifepoints, mo->pos.y, mo->pos.x);
+        try_fwrite(line, strlen(line), 1, file, world, f_name);
+        mo = mo->next;
     }
-    return 0;
 }
 
 
 
-extern void * build_map_objects(struct World * world, void * start, char def_id,
-                                uint8_t n)
+extern void read_map_objects(struct World * world, FILE * file, char * line,
+                              int linemax)
 {
-    char * err = "Trouble in build_map_objects() with get_next_map_obj().";
-    uint8_t i;
-    struct MapObj * mo;
-    uint8_t first = 1;
-    struct MapObjDef * mod = get_map_obj_def(world, def_id);
-    size_t size = 0;
-    if ('i' == mod->m_or_i)
-    {
-        size = sizeof(struct Item);
-    }
-    else
-    {
-        size = sizeof(struct Monster);
-    }
-    for (i = 0; i < n; i++)
+    char * f_name = "read_map_objects()";
+    struct MapObj ** mo_ptr_ptr = &world->map_objs;
+    char * delim = " ";
+    while (try_fgets(line, linemax + 1, file, world, f_name))
     {
-        mo = get_next_map_obj(world, start, &first, size, mo);
-        exit_err(NULL == mo, world, err);
-        mo->pos = find_passable_pos(world->map);
-        mo->id = world->map_object_count;
-        world->map_object_count++;
-        if ('i' == mod->m_or_i)
+        struct MapObj * mo = malloc(sizeof(struct MapObj));
+        mo->next = NULL;
+        mo->id = atoi(strtok(line, delim));
+        if (mo->id > world->map_obj_count)
         {
-            build_map_objects_itemdata(mod, mo);
-        }
-        else
-        {
-            build_map_objects_monsterdata(mod, mo);
+            world->map_obj_count = mo->id;
         }
+        mo->type = atoi(strtok(NULL, delim));
+        mo->lifepoints = atoi(strtok(NULL, delim));
+        mo->pos.y = atoi(strtok(NULL, delim));
+        mo->pos.x = atoi(strtok(NULL, delim));
+        * mo_ptr_ptr = mo;
+        mo_ptr_ptr = &mo->next;
     }
-    if (!first)
-    {
-        mo->next = 0;
-    }
-    return &mo->next;
 }
 
 
 
-extern void free_items(struct Item * item)
+extern struct MapObj ** build_map_objects(struct World * w,
+                                           struct MapObj ** mo_ptr_ptr,
+                                           uint8_t type, uint8_t n)
 {
-    if (0 == item)
+    char * f_name = "build_map_objects()";
+    uint8_t i = 0;
+    struct MapObjDef * mod = get_map_object_def(w, type);
+    while (i < n)
     {
-        return;
+        struct MapObj * mo = try_malloc(sizeof(struct MapObj), w, f_name);
+        mo->id = w->map_obj_count;
+        w->map_obj_count++;
+        mo->type = mod->id;
+        mo->next = NULL;
+        mo->lifepoints = mod->lifepoints;
+        mo->pos = find_passable_pos(w->map);
+        i++;
+        * mo_ptr_ptr = mo;
+        mo_ptr_ptr = &mo->next;
     }
-    free_items((struct Item *) item->map_obj.next);
-    free(item);
+    return mo_ptr_ptr;
 }
 
 
 
-extern void free_monsters(struct Monster * monster)
+extern void free_map_objects(struct MapObj * mo_start)
 {
-    if (0 == monster)
+    if (NULL == mo_start)
     {
         return;
     }
-    free_monsters((struct Monster *) monster->map_obj.next);
-    free(monster);
+    free_map_objects(mo_start->next);
+    free(mo_start);
 }
 
 
 
-extern struct MapObjDef * get_map_obj_def(struct World * world, char def_id)
+extern struct MapObjDef * get_map_object_def(struct World * w, uint8_t id)
 {
-    struct MapObjDef * d = NULL;
-    for (d = (struct MapObjDef *) world->monster_def;
-         d->id != def_id && 0 != d->next;
-         d = d->next);
-    if (d->id != def_id)
+    struct MapObjDef * mod = w->map_obj_defs;
+    while (id != mod->id)
     {
-        for (d = (struct MapObjDef *) world->item_def;
-             d->id != def_id && 0 != d->next;
-             d = d->next);
+        mod = mod->next;
     }
-    return d;
+    return mod;
 }
index 2307fb51fe776bb09f52e816b7294be86554dd49..29bae854045e4ad04d5a51ec2cae53dbff3bba98 100644 (file)
@@ -25,92 +25,62 @@ struct Player
 
 
 
-/* Structs for standard map objects. */
-
 struct MapObj
 {
-    void * next;
-    uint8_t id;           /* Unique identifier of individual map object. */
-    char type;            /* Map object type identifier (see MapObjDef.id). */
-    struct yx_uint16 pos; /* Coordinate of object on map. */
+    struct MapObj * next;        /* pointer to next one in map object chain */
+    uint8_t id;                  /* individual map object's unique identifier */
+    uint8_t type;                /* ID of appropriate map object definition */
+    uint8_t lifepoints;          /* 0: object is inanimate; >0: hitpoints */
+    struct yx_uint16 pos;        /* coordinate on map */
 };
 
-struct Item
-{
-    struct MapObj map_obj;
-};
-
-struct Monster
-{
-    struct MapObj map_obj;
-    uint8_t hitpoints;
-};
-
-
 
-/* Structs for map object *type* definitions. Values common to all members of
- * a single monster or item type are harvested from these.
- */
 
 struct MapObjDef
 {
     struct MapObjDef * next;
-    char m_or_i;  /* Is it item or monster? "i" for items, "m" for monsters. */
-    char id;      /* Unique identifier of the map object type to describe. */
-    char mapchar; /* Map object symbol to appear on map.*/
-    char * desc;  /* String describing map object in the game log. */
+    uint8_t id;         /* unique identifier of map object type */
+    uint8_t corpse_id;  /* id of type to change into upon destruction */
+    char char_on_map;   /* map object symbol to appear on map */
+    char * name;        /* string to describe object in game log*/
+    uint8_t lifepoints; /* default value for map object lifepoints member */
 };
 
-struct ItemDef
-{
-    struct MapObjDef map_obj_def;
-};
 
-struct MonsterDef
-{
-    struct MapObjDef map_obj_def;
-    uint8_t corpse_id;       /* ID of object type killed monster changes to. */
-    uint8_t hitpoints_start; /* Hitpoints each monster starts with. */
-};
 
+/* Initialize map object defnitions chain from file at path "filename". */
+extern void init_map_object_defs(struct World * world, char * filename);
 
 
-/* Initialize map object type definitions from file at path "filename". */
-extern void init_map_object_defs(struct World * world, char * filename);
 
+/* Free map object definitions chain starting at "mod_start". */
+extern void free_map_object_defs(struct MapObjDef * mod_start);
 
 
-/* Free item / monster definitions in map object chain starting at "md_start" /
- * "id_start".
- */
-extern void free_item_defs(struct ItemDef * id_start);
-extern void free_monster_defs(struct MonsterDef * md_start);
+/* Build chain of "n" map objects of "tpye" to start at "mo_ptr_ptr". */
+extern struct MapObj ** build_map_objects(struct World * w,
+                                          struct MapObj ** mo_ptr_ptr,
+                                          uint8_t type, uint8_t n);
 
 
+/* Write map objects chain to "file". */
+extern void write_map_objects(struct World * world, FILE * file);
 
-/* Build into memory starting at "start" chain of "n" map objects of type
- * "def_id".
+/* Read from "file" map objects chain; use "line" as char array for fgets() and
+ * expect strings of max. "linemax" length.
  */
-extern void * build_map_objects(struct World * world, void * start, char def_id,
-                                uint8_t n);
+extern void read_map_objects(struct World * world, FILE * file,
+                             char * line, int linemax);
 
 
 
-/* Write to/read from file chain of map objects starting/to start in memory at
- * "start".
- */
-extern uint8_t write_map_objects(struct World * world, void * start,
-                                 FILE * file);
-extern uint8_t read_map_objects(struct World * world, void * start,
-                                FILE * file);
+/* Free map objects in map object chain starting at "mo_start. */
+extern void free_map_objects(struct MapObj * mo_start);
 
 
-/* Free items / monsters in map object chain starting at "item" / "monster". */
-extern void free_items(struct Item * item);
-extern void free_monsters(struct Monster * monster);
 
 /* Get pointer to the map object definition of identifier "def_id". */
-extern struct MapObjDef * get_map_obj_def(struct World * world, char def_id);
+extern struct MapObjDef * get_map_object_def(struct World * w, uint8_t id);
 
 
 
index e3499c10f7cd4f048a156a695e8cefb95415e712..16ddc38a3f89cbff028bc1729cb34597fbe20bb8 100644 (file)
@@ -9,7 +9,9 @@
 #include "readwrite.h" /* for [read/write]_uint[8/16/32][_bigendian](),
                         * try_fopen(), try_fclose()
                         */
-#include "map_objects.h" /* for struct Monster, write_map_objects(), */
+#include "map_objects.h" /* for struct Monster, read_map_objects(),
+                          * write_map_objects()
+                          */
 #include "map_object_actions.h" /* for is_passable(), move_monster() */
 #include "map.h" /* for Map struct */
 #include "main.h" /* for World struct */
@@ -215,12 +217,15 @@ extern void turn_over(struct World * world, char action)
     }
     world->turn++;
     rrand_seed(world->seed * world->turn);
-    struct Monster * monster;
-    for (monster = world->monster;
+    struct MapObj * monster;
+    for (monster = world->map_objs;
          monster != 0;
-         monster = monster->map_obj.next)
+         monster = monster->next)
     {
-        move_monster(world, monster);
+        if (0 < monster->lifepoints)
+        {
+            move_monster(world, monster);
+        }
     }
 }
 
@@ -229,28 +234,56 @@ extern void turn_over(struct World * world, char action)
 extern void save_game(struct World * world)
 {
     char * f_name = "save_game()";
-    char * err_write = "Trouble in save_game() "
-                       "writing to opened file 'savefile_tmp'.";
 
     char * savefile_tmp = "savefile_tmp";
     char * savefile     = "savefile";
     FILE * file = try_fopen(savefile_tmp, "w", world, f_name);
-    if (   write_uint32_bigendian(world->seed, file)
-        || write_uint32_bigendian(world->turn, file)
-        || write_uint16_bigendian(world->score, file)
-        || write_uint16_bigendian(world->player->pos.y + 1, file)
-        || write_uint16_bigendian(world->player->pos.x + 1, file)
-        || write_uint8(world->player->hitpoints, file)
-        || write_map_objects(world, world->monster, file)
-        || write_map_objects(world, world->item, file))
-    {
-        exit_err(1, world, err_write);
-    }
+
+    char line[12];
+    sprintf(line, "%d\n", world->seed);
+    try_fwrite(line, strlen(line), 1, file, world, f_name);
+    sprintf(line, "%d\n", world->turn);
+    try_fwrite(line, strlen(line), 1, file, world, f_name);
+    sprintf(line, "%d\n", world->score);
+    try_fwrite(line, strlen(line), 1, file, world, f_name);
+    sprintf(line, "%d\n", world->player->hitpoints);
+    try_fwrite(line, strlen(line), 1, file, world, f_name);
+    sprintf(line, "%d\n", world->player->pos.y);
+    try_fwrite(line, strlen(line), 1, file, world, f_name);
+    sprintf(line, "%d\n", world->player->pos.x);
+    try_fwrite(line, strlen(line), 1, file, world, f_name);
+    write_map_objects(world, file);
+
     try_fclose_unlink_rename(file, savefile_tmp, savefile, world, f_name);
 }
 
 
 
+extern void load_game(struct World * world)
+{
+    char * f_name = "load_game2()";
+    char * filename = "savefile";
+    FILE * file = try_fopen(filename, "r", world, f_name);
+    uint16_t linemax = get_linemax(file, world, f_name);
+    char line[linemax + 1];
+    try_fgets(line, linemax + 1, file, world, f_name);
+    world->seed = atoi(line);
+    try_fgets(line, linemax + 1, file, world, f_name);
+    world->turn = atoi(line);
+    try_fgets(line, linemax + 1, file, world, f_name);
+    world->score = atoi(line);
+    try_fgets(line, linemax + 1, file, world, f_name);
+    world->player->hitpoints = atoi(line);
+    try_fgets(line, linemax + 1, file, world, f_name);
+    world->player->pos.y = atoi(line);
+    try_fgets(line, linemax + 1, file, world, f_name);
+    world->player->pos.x = atoi(line);
+    read_map_objects(world, file, line, linemax);
+    try_fclose(file, world, f_name);
+}
+
+
+
 extern struct yx_uint16 find_passable_pos(struct Map * map)
 {
     struct yx_uint16 pos;
index 831c4d1170d32374c73b04b38f10ecf8a69c1f93..b6923087b5068f20af114e6d118347d409797207 100644 (file)
@@ -66,8 +66,9 @@ extern void turn_over(struct World * world, char action);
 
 
 
-/* Save current game data to file "savefile". */
+/* Save or load current game data to / from file "savefile". */
 extern void save_game(struct World * world);
+extern void load_game(struct World * world);
 
 
 
index 09faaeb282dcb8a84731c5c1bce3c69b2dd41c77..657d8173dd674ecfa9528cfce9653ee5dd841449 100644 (file)
@@ -2,7 +2,7 @@
 
 #include "readwrite.h"
 #include <stdio.h>  /* for FILE typedef, fopen(), fgetc(), fputc(), fseek(),
-                     * sprintf(), fwrite()
+                     * sprintf(), fwrite(), ferror()
                      */
 #include <stdint.h> /* for uint8_t, uint16_t, uint32_t */
 #include <string.h> /* for strlen()*/
@@ -59,12 +59,14 @@ extern void try_fclose(FILE * file, struct World * w, char * f)
 
 
 
-extern void try_fgets(char * line, int linemax, FILE * file,
-                      struct World * w, char * f)
+extern char * try_fgets(char * line, int linemax, FILE * file,
+                        struct World * w, char * f)
 {
     char * msg = trouble_msg(w, f, "fgets()");
-    exit_err(NULL == fgets(line, linemax, file), w, msg);
+    char * test = fgets(line, linemax, file);
+    exit_err(NULL == test && ferror(file), w, msg);
     free(msg);
+    return test;
 }
 
 
index bebcdc058c39ee6c1298f0b37acf8fec2858efbe..99d490c6c2c3a23fa35f6949486780e105ba4de4 100644 (file)
@@ -19,13 +19,20 @@ struct World;
  */
 extern FILE * try_fopen(char * path, char * mode, struct World * w, char * f);
 extern void try_fclose(FILE * file, struct World * w, char * f);
-extern void try_fgets(char * line, int size, FILE * file,
-                      struct World * w, char * f);
 extern void try_fwrite(void * ptr, size_t size, size_t nmemb, FILE * stream,
                        struct World * w, char * f);
 
 
 
+/* Wrapper to calling fgets() from function called "f". The return code of
+ * fgets() is returned unless it is NULL *and* ferror() indicates that an error
+ * occured; otherwise end of file is assumed and NULL is returned properly.
+ */
+extern char * try_fgets(char * line, int size, FILE * file,
+                        struct World * w, char * f);
+
+
+
 /* Wrapper to successive call of fclose() from function called "f" on "file",
  * then unlink() on file at "p2" if it exists, then rename() on "p1" to "p2".
  * Used for handling atomic saving of files via temp files.
index 1bc639f3a64ca147c6025f4943dddfb6d073a625..5fa660ea2175e925855bf6c6323ab18312a9335c 100644 (file)
@@ -11,7 +11,7 @@
 #include "keybindings.h" /* for free_keybindings() */
 #include "command_db.h" /* for free_command_db() */
 #include "windows.h" /* for Win struct, free_win(), free_winmeta() */
-#include "map_objects.h" /* for free_item_defs(), free_monster_defs() */
+#include "map_objects.h" /* for free_map_objects, free_map_object_defs() */
 #include "wincontrol.h" /* for free_winconfs() */
 #include "misc.h" /* for unload_interface_conf() */
 
@@ -31,13 +31,11 @@ static void cleanup(struct World * world)
     }
     if (cleanup_flags & CLEANUP_MAP_OBJECTS)
     {
-        free_items(world->item);
-        free_monsters(world->monster);
+        free_map_objects(world->map_objs);
     }
     if (cleanup_flags & CLEANUP_MAP_OBJECT_DEFS)
     {
-        free_item_defs(world->item_def);
-        free_monster_defs(world->monster_def);
+        free_map_object_defs(world->map_obj_defs);
     }
     if (cleanup_flags & CLEANUP_LOG)
     {
@@ -59,18 +57,6 @@ static void cleanup(struct World * world)
     {
         free_winmeta(world->wmeta);
     }
-/*
-    if (cleanup_flags & CLEANUP_KEYBINDINGS)
-    {
-        free_keybindings(world->kb_global.kbs);
-        free_keybindings(world->kb_wingeom.kbs);
-        free_keybindings(world->kb_winkeys.kbs);
-    }
-    if (cleanup_flags & CLEANUP_WINCONFS)
-    {
-        free_winconfs(world);
-    }
-*/
 }