#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() */
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);
}
}
}
}
- 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,
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);
#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() */
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()) / "
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. */
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;
}
struct WinMeta;
struct WinConf;
struct Win;
-struct KeyBinding;
-struct KeysWinData;
struct Map;
-struct ItemDef;
-struct MonsterDef;
+struct MapObjDef;
+struct MapObj;
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. */
};
/* 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() */
/* 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.
* 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.
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);
}
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.");
-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);
}
}
-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;
}
if (is_passable(world->map, t))
{
- monster->map_obj.pos = t;
+ monster->pos = t;
}
}
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);
#include "yx_uint16.h" /* for yx_uint16 coordinates */
struct World;
struct Map;
-struct Monster;
+struct MapObj;
* 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);
-/* 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;
}
-/* 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);
#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 */
}
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);
+ }
}
}
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;
-/* 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);
#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()*/
-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;
}
*/
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.
#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() */
}
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)
{
{
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);
- }
-*/
}