From: Christian Heller Date: Mon, 23 Sep 2013 01:55:49 +0000 (+0200) Subject: Re-wrote map object system to use same structs for items and monsters, and switched... X-Git-Tag: tce~952 X-Git-Url: https://plomlompom.com/repos/%7B%7B%20web_path%20%7D%7D/decks/%7B%7Bprefix%7D%7D/static/blog?a=commitdiff_plain;h=fb8ddca6abc66eb7e52a007850689309b4cda938;p=plomrogue Re-wrote map object system to use same structs for items and monsters, and switched to plain-text savefile. --- diff --git a/src/draw_wins.c b/src/draw_wins.c index 53ce68d..2b04ff4 100644 --- a/src/draw_wins.c +++ b/src/draw_wins.c @@ -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, diff --git a/src/draw_wins.h b/src/draw_wins.h index c86f367..3ebdf76 100644 --- a/src/draw_wins.h +++ b/src/draw_wins.h @@ -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); diff --git a/src/main.c b/src/main.c index 8d00a5d..fcaac80 100644 --- a/src/main.c +++ b/src/main.c @@ -6,20 +6,19 @@ #include /* for initscr(), noecho(), curs_set(), keypad(), raw() */ #include /* for time() */ #include /* for getopt(), optarg */ -#include /* for uint16_t, uint32_t */ +#include /* 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; } diff --git a/src/main.h b/src/main.h index 83bdb83..a290099 100644 --- a/src/main.h +++ b/src/main.h @@ -13,11 +13,9 @@ 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. */ }; diff --git a/src/map_object_actions.c b/src/map_object_actions.c index 1b14339..23152e2 100644 --- a/src/map_object_actions.c +++ b/src/map_object_actions.c @@ -1,13 +1,14 @@ /* map_object_actions.c */ #include "map_object_actions.h" -#include /* for free() */ #include /* 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); diff --git a/src/map_object_actions.h b/src/map_object_actions.h index 6034611..ae764b9 100644 --- a/src/map_object_actions.h +++ b/src/map_object_actions.h @@ -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); diff --git a/src/map_objects.c b/src/map_objects.c index 485ab6d..e690281 100644 --- a/src/map_objects.c +++ b/src/map_objects.c @@ -14,329 +14,133 @@ -/* 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; } diff --git a/src/map_objects.h b/src/map_objects.h index 2307fb5..29bae85 100644 --- a/src/map_objects.h +++ b/src/map_objects.h @@ -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); diff --git a/src/misc.c b/src/misc.c index e3499c1..16ddc38 100644 --- a/src/misc.c +++ b/src/misc.c @@ -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; diff --git a/src/misc.h b/src/misc.h index 831c4d1..b692308 100644 --- a/src/misc.h +++ b/src/misc.h @@ -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); diff --git a/src/readwrite.c b/src/readwrite.c index 09faaeb..657d817 100644 --- a/src/readwrite.c +++ b/src/readwrite.c @@ -2,7 +2,7 @@ #include "readwrite.h" #include /* for FILE typedef, fopen(), fgetc(), fputc(), fseek(), - * sprintf(), fwrite() + * sprintf(), fwrite(), ferror() */ #include /* for uint8_t, uint16_t, uint32_t */ #include /* 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; } diff --git a/src/readwrite.h b/src/readwrite.h index bebcdc0..99d490c 100644 --- a/src/readwrite.h +++ b/src/readwrite.h @@ -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. diff --git a/src/rexit.c b/src/rexit.c index 1bc639f..5fa660e 100644 --- a/src/rexit.c +++ b/src/rexit.c @@ -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); - } -*/ }