/* * Copyright (C) 2002-2007 The Warp Rogue Team * Part of the Warp Rogue Project * * This software is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License. * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY. * * See the license.txt file for more details. */ /* * Module Name: LoadSave * Description: - */ #define Uses_Ui #define Uses_Macro #define Uses_Round #define Uses_World #define Uses_Area #define Uses_Death #define Uses_World #define Uses_Util #define Uses_Terrain #define Uses_Character #define Uses_Object #define Uses_Npc #define Uses_Inventory #define Uses_Event #define Uses_ProgramManager #define Uses_Party #define Uses_Game #define Uses_Options #define Uses_DataFile #define Uses_Scenario #include "mheader.h" #include "rdb.h" #include "loadsave.h" #define FILE_SAVE_POINT_AREA "sp_area.rdb" #define FILE_GAME_STATE "state.rdb" static void game_state_write(void); static bool game_state_read(void); static const char * area_file_name(const WORLD_POINT *); static void area_terrain_list_write(void); static void area_terrain_list_read(void); static void area_object_list_write(void); static void area_object_list_read(void); static void area_character_list_write(void); static void area_character_list_read(void); static void area_event_list_write(void); static void area_event_list_read(void); static void area_sectors_write(void); static void area_sectors_read(void); static void sector_write(const SECTOR *); static SECTOR sector_read(void); static void terrain_pointer_write(const TERRAIN *); static TERRAIN * terrain_pointer_read(void); static void object_pointer_write(const OBJECT *); static OBJECT * object_pointer_read(void); static void character_pointer_write(const CHARACTER *); static CHARACTER * character_pointer_read(void); static void terrain_write(const TERRAIN *); static TERRAIN * terrain_read(void); static void object_write(const OBJECT *); static OBJECT * object_read(void); static void character_write(const CHARACTER *); static CHARACTER * character_read(void); static void character_stats_write(const CHARACTER_STAT *); static void character_stats_read(CHARACTER_STAT *); static void character_inventory_write(const CHARACTER *); static void character_inventory_read(LIST *); static void event_write(const EVENT *); static EVENT * event_read(void); static void version_write(void); static bool file_is_compatible(void); static void difficulty_write(void); static void difficulty_read(void); static void time_write(void); static void time_read(void); static void visible_area_write(void); static void visible_area_read(void); static void macros_write(void); static void macros_read(void); static void npc_counter_write(void); static void npc_counter_read(void); static void world_point_write(const WORLD_POINT *); static void world_point_read(WORLD_POINT *); static void area_point_write(const AREA_POINT *); static void area_point_read(AREA_POINT *); static void area_section_write(const AREA_SECTION *); static void area_section_read(AREA_SECTION *); static void ai_data_write(const AI_DATA *); static void ai_data_read(AI_DATA *); static void bool_array_write(const bool *, int); static void bool_array_read(bool *, int); /* * these arrays are used to speed up pointer restoration */ static TERRAIN ** TerrainRestore = NULL; static OBJECT ** ObjectRestore = NULL; static CHARACTER ** CharacterRestore = NULL; /* * creates a save point */ void save_point_create(void) { game_state_write(); area_write(FILE_SAVE_POINT_AREA); } /* * loads a save point */ bool save_point_load(void) { if (!game_state_read()) { return false; } area_read(NULL); update_view_character(player_controlled_character()); return true; } /* * returns true if a save point exists */ bool save_point_exists(void) { set_data_path(DIR_USER_DATA, FILE_SAVE_POINT_AREA); if (file_exists(data_path())) { return true; } return false; } /* * deletes all saved world data */ void world_erase(void) { LIST *file_list; LIST_NODE *node; file_list = data_files(DIR_USER_DATA); for (node = file_list->head; node != NULL; node = node->next) { const char *file_name; file_name = (const char *)node->data; set_data_path(DIR_USER_DATA, file_name); remove(data_path()); } list_free_with(file_list, free); } /* * writes the active area */ void area_write(const char *file_name) { AREA *area; area = active_area(); if (file_name == NULL) { set_data_path(DIR_USER_DATA, area_file_name(&area->location)); } else { set_data_path(DIR_USER_DATA, file_name); } rdb_open(data_path(), RDB_WRITE); rdb_write_field_name("N"); rdb_write_string(area->name); world_point_write(&area->location); area_terrain_list_write(); area_object_list_write(); area_character_list_write(); area_event_list_write(); area_sectors_write(); rdb_close(); } /* * reads an area */ void area_read(const WORLD_POINT *coord) { AREA *area; if (coord == NULL) { set_data_path(DIR_USER_DATA, FILE_SAVE_POINT_AREA); } else { set_data_path(DIR_USER_DATA, area_file_name(coord)); } rdb_open(data_path(), RDB_READ); area = active_area(); rdb_next_field(); strcpy(area->name, rdb_data_token(RDB_NEXT_TOKEN)); world_point_read(&area->location); area_terrain_list_read(); area_object_list_read(); area_character_list_read(); area_event_list_read(); area_sectors_read(); rdb_close(); if (TerrainRestore != NULL) free(TerrainRestore); if (ObjectRestore != NULL) free(ObjectRestore); if (CharacterRestore != NULL) free(CharacterRestore); } /* * returns true if an area exists at the passed point */ bool area_exists(const WORLD_POINT *world_point) { set_data_path(DIR_USER_DATA, area_file_name(world_point)); if (file_exists(data_path())) { return true; } return false; } /* * writes the game state file */ static void game_state_write(void) { set_data_path(DIR_USER_DATA, FILE_GAME_STATE); rdb_open(data_path(), RDB_WRITE); version_write(); difficulty_write(); time_write(); visible_area_write(); macros_write(); npc_counter_write(); rdb_close(); } /* * reads the game state file */ static bool game_state_read(void) { set_data_path(DIR_USER_DATA, FILE_GAME_STATE); rdb_open(data_path(), RDB_READ); if (!file_is_compatible()) { return false; } difficulty_read(); time_read(); visible_area_read(); macros_read(); npc_counter_read(); rdb_close(); return true; } /* * returns the file name of an area */ static const char * area_file_name(const WORLD_POINT *point) { static char file_name[FILE_NAME_SIZE]; sprintf(file_name, "%02d%02d%02d.rdb", point->z, point->y, point->x ); return file_name; } /* * writes the area terrain list */ static void area_terrain_list_write(void) { LIST_NODE *node; TERRAIN *terrain; int n_terrain_objects; LIST_NODE_INDEX index; n_terrain_objects = area_terrain_list()->n_nodes; rdb_write_field_name("N"); rdb_write_integer(n_terrain_objects); for (node = area_terrain_list()->head, index = 0; node != NULL; node = node->next, index++) { terrain = (TERRAIN *)node->data; terrain->list_index = index; terrain_write(terrain); } } /* * reads the area terrain list */ static void area_terrain_list_read(void) { int i, n_terrain_objects; TERRAIN *terrain; AREA *area; area = active_area(); rdb_next_field(); n_terrain_objects = atoi(rdb_data_token(RDB_NEXT_TOKEN)); if (n_terrain_objects == 0) { TerrainRestore = NULL; return; } TerrainRestore = checked_malloc( n_terrain_objects * sizeof *TerrainRestore ); for (i = 0; i < n_terrain_objects; i++) { terrain = terrain_read(); terrain->list_node = list_add(area->terrain, terrain); TerrainRestore[i] = terrain; } } /* * writes the area object list */ static void area_object_list_write(void) { LIST_NODE *node; OBJECT *object; N_OBJECTS n_objects; LIST_NODE_INDEX index; n_objects = area_object_list()->n_nodes; rdb_write_field_name("N"); rdb_write_integer(n_objects); for (node = area_object_list()->head, index = 0; node != NULL; node = node->next, index++) { object = (OBJECT *)node->data; object->list_index = index; object_write(object); } } /* * reads the area object list */ static void area_object_list_read(void) { N_OBJECTS n_objects; OBJECT *object; AREA *area; int i; area = active_area(); rdb_next_field(); n_objects = atoi(rdb_data_token(RDB_NEXT_TOKEN)); if (n_objects == 0) { ObjectRestore = NULL; return; } ObjectRestore = checked_malloc( n_objects * sizeof *ObjectRestore ); for (i = 0; i < n_objects; i++) { object = object_read(); object->list_node = list_add(area->objects, object); ObjectRestore[i] = object; } } /* * writes the area character list */ static void area_character_list_write(void) { LIST_NODE *node; CHARACTER *character; N_CHARACTERS n_characters; LIST_NODE_INDEX index; n_characters = area_character_list()->n_nodes; rdb_write_field_name("N"); rdb_write_integer(n_characters); for (node = area_character_list()->head, index = 0; node != NULL; node = node->next, index++) { character = (CHARACTER *)node->data; character->list_index = index; character_write(character); } } /* * reads the area character list */ static void area_character_list_read(void) { CHARACTER *character; N_CHARACTERS n_characters; AREA *area; int i; area = active_area(); rdb_next_field(); n_characters = atoi(rdb_data_token(RDB_NEXT_TOKEN)); if (n_characters == 0) { CharacterRestore = NULL; return; } CharacterRestore = checked_malloc( n_characters * sizeof *CharacterRestore ); for (i = 0; i < n_characters; i++) { character = character_read(); character->list_node = list_add(area->characters, character); CharacterRestore[i] = character; } } /* * writes the area event list */ static void area_event_list_write(void) { LIST_NODE *node; const EVENT *event; N_EVENTS n_events; n_events = area_event_list()->n_nodes; rdb_write_field_name("N"); rdb_write_integer(n_events); for (node = area_event_list()->head; node != NULL; node = node->next) { event = (const EVENT *)node->data; event_write(event); } } /* * reads the area event list */ static void area_event_list_read(void) { N_EVENTS n_events; EVENT *event; AREA *area; area = active_area(); rdb_next_field(); n_events = atoi(rdb_data_token(RDB_NEXT_TOKEN)); for ( ; n_events > 0; n_events--) { event = event_read(); list_add(area->events, event); } } /* * writes the area sectors */ static void area_sectors_write(void) { AREA_POINT p; const AREA_SECTION *bounds; bounds = area_bounds(); for (p.y = bounds->top; p.y <= bounds->bottom; p.y++) { for (p.x = bounds->left; p.x <= bounds->right; p.x++) { const SECTOR *sector; sector = sector_at(&p); sector_write(sector); } } } /* * reads the area sectors */ static void area_sectors_read(void) { AREA *area; AREA_POINT p; const AREA_SECTION *bounds; area = active_area(); bounds = area_bounds(); for (p.y = bounds->top; p.y <= bounds->bottom; p.y++) { for (p.x = bounds->left; p.x <= bounds->right; p.x++) { SECTOR *sector; sector = sector_at(&p); *sector = sector_read(); } } } /* * writes a sector */ static void sector_write(const SECTOR *sector) { rdb_write_field_name("S"); character_pointer_write(sector->character); object_pointer_write(sector->object); terrain_pointer_write(sector->terrain); } /* * reads a sector */ static SECTOR sector_read(void) { SECTOR sector; rdb_next_field(); sector.character = character_pointer_read(); sector.object = object_pointer_read(); sector.terrain = terrain_pointer_read(); return sector; } /* * writes a terrain pointer */ static void terrain_pointer_write(const TERRAIN *terrain) { if (terrain == NULL) { rdb_write_string(""); } else { rdb_write_integer(terrain->list_index); } } /* * reads a terrain pointer */ static TERRAIN * terrain_pointer_read(void) { TERRAIN *terrain; const char *token; token = rdb_data_token(RDB_NEXT_TOKEN); if (is_empty_string(token)) { return NULL; } terrain = TerrainRestore[atoi(token)]; return terrain; } /* * writes an object pointer */ static void object_pointer_write(const OBJECT *object) { if (object == NULL) { rdb_write_string(""); } else { rdb_write_integer(object->list_index); } } /* * reads an object pointer */ static OBJECT * object_pointer_read(void) { OBJECT *object; const char *token; token = rdb_data_token(RDB_NEXT_TOKEN); if (is_empty_string(token)) { return NULL; } object = ObjectRestore[atoi(token)]; return object; } /* * writes a character pointer */ static void character_pointer_write(const CHARACTER *character) { if (character == NULL) { rdb_write_string(""); } else { rdb_write_integer(character->list_index); } } /* * reads a character pointer */ static CHARACTER * character_pointer_read(void) { CHARACTER *character; const char *token; token = rdb_data_token(RDB_NEXT_TOKEN); if (is_empty_string(token)) { return NULL; } character = CharacterRestore[atoi(token)]; return character; } /* * writes a terrain */ static void terrain_write(const TERRAIN *terrain) { rdb_write_field_name("T"); rdb_write_integer(terrain->index); rdb_write_integer(terrain->colour); rdb_write_integer(terrain->gore_level); } /* * reads a terrain */ static TERRAIN * terrain_read(void) { TERRAIN *terrain; terrain = checked_malloc(sizeof *terrain); rdb_next_field(); terrain->index = atoi(rdb_data_token(RDB_NEXT_TOKEN)); terrain->colour = atoi(rdb_data_token(RDB_NEXT_TOKEN)); terrain->gore_level = atoi(rdb_data_token(RDB_NEXT_TOKEN)); return terrain; } /* * writes an object */ static void object_write(const OBJECT *object) { rdb_write_field_name("O"); rdb_write_integer(object->index); rdb_write_integer(object->colour); rdb_write_integer(object->gore_level); rdb_write_integer(object->condition); rdb_write_integer(object->charge); rdb_write_integer(object->functional); } /* * reads an object */ static OBJECT * object_read(void) { OBJECT *object; object = checked_malloc(sizeof *object); rdb_next_field(); object->index = atoi(rdb_data_token(RDB_NEXT_TOKEN)); object->colour = atoi(rdb_data_token(RDB_NEXT_TOKEN)); object->gore_level = atoi(rdb_data_token(RDB_NEXT_TOKEN)); object->condition = atoi(rdb_data_token(RDB_NEXT_TOKEN)); object->charge = atoi(rdb_data_token(RDB_NEXT_TOKEN)); object->functional = (bool)atoi(rdb_data_token(RDB_NEXT_TOKEN)); return object; } /* * writes a character */ static void character_write(const CHARACTER *character) { rdb_write_field_name("C"); rdb_write_string(character->name); rdb_write_string(character->script); rdb_write_integer(character->type); rdb_write_integer(character->controller); rdb_write_integer(character->party); rdb_write_integer(character->is_hostile); rdb_write_integer(character->numerus); rdb_write_integer(character->symbol); rdb_write_integer(character->colour); rdb_write_integer(character->gender); rdb_write_integer(character->career); rdb_write_integer(character->ep); rdb_write_integer(character->ep_total); rdb_write_integer(character->action_spent); rdb_write_integer(character->bloody_feet); rdb_write_integer(character->concentration); rdb_write_integer(character->armour_rating.current); rdb_write_integer(character->armour_rating.total); rdb_write_integer(character->injury); rdb_write_integer(character->index); area_point_write(&character->location); ai_data_write(&character->ai); character_stats_write(character->stat); rdb_write_field_name("F"); bool_array_write(character->flag, MAX_CHARACTER_FLAGS); rdb_write_field_name("K"); bool_array_write(character->perk, MAX_PERKS); rdb_write_field_name("Y"); bool_array_write(character->psy_power, MAX_PSY_POWERS); rdb_write_field_name("E"); object_pointer_write(character->weapon); object_pointer_write(character->secondary_weapon); object_pointer_write(character->armour); object_pointer_write(character->jump_pack); character_inventory_write(character); } /* * reads a character */ static CHARACTER * character_read(void) { CHARACTER *character; character = character_new(); rdb_next_field(); strcpy(character->name, rdb_data_token(RDB_NEXT_TOKEN)); strcpy(character->script, rdb_data_token(RDB_NEXT_TOKEN)); character->type = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->controller = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->party = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->is_hostile = (bool)atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->numerus = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->symbol = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->colour = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->gender = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->career = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->ep = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->ep_total = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->action_spent = (bool)atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->bloody_feet = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->concentration = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->armour_rating.current = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->armour_rating.total = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->injury = atoi(rdb_data_token(RDB_NEXT_TOKEN)); character->index = atoi(rdb_data_token(RDB_NEXT_TOKEN)); area_point_read(&character->location); ai_data_read(&character->ai); character_stats_read(character->stat); rdb_next_field(); bool_array_read(character->flag, MAX_CHARACTER_FLAGS); rdb_next_field(); bool_array_read(character->perk, MAX_PERKS); rdb_next_field(); bool_array_read(character->psy_power, MAX_PSY_POWERS); rdb_next_field(); character->weapon = object_pointer_read(); character->secondary_weapon = object_pointer_read(); character->armour = object_pointer_read(); character->jump_pack = object_pointer_read(); character_inventory_read(character->inventory); if (character->type == CT_PC) { set_player_character(character); } if (character->controller == CC_PLAYER) { set_player_controlled_character(character); } if (character->party == PARTY_PLAYER) { list_add(party_player(), character); } return character; } /* * writes character stats */ static void character_stats_write(const CHARACTER_STAT *p) { int i; rdb_write_field_name("S"); for (i = 0; i < MAX_STATS; i++) { rdb_write_integer(p[i].current); rdb_write_integer(p[i].total); rdb_write_integer(p[i].advance); } } /* * reads character stats */ static void character_stats_read(CHARACTER_STAT *p) { int i; rdb_next_field(); for (i = 0; i < MAX_STATS; i++) { p[i].current = atoi(rdb_data_token(RDB_NEXT_TOKEN)); p[i].total = atoi(rdb_data_token(RDB_NEXT_TOKEN)); p[i].advance = atoi(rdb_data_token(RDB_NEXT_TOKEN)); } } /* * writes a character inventory */ static void character_inventory_write(const CHARACTER *character) { LIST_NODE *node; OBJECT *object; N_OBJECTS n_objects; n_objects = character->inventory->n_nodes; rdb_write_field_name("I"); rdb_write_integer(n_objects); for (node = character->inventory->head; node != NULL; node = node->next) { object = (OBJECT *)node->data; object_pointer_write(object); } } /* * reads a character inventory */ static void character_inventory_read(LIST *inventory) { N_OBJECTS n_objects; OBJECT *object; rdb_next_field(); n_objects = atoi(rdb_data_token(RDB_NEXT_TOKEN)); for ( ; n_objects > 0; n_objects--) { object = object_pointer_read(); list_add(inventory, object); } } /* * writes an event */ static void event_write(const EVENT *event) { int i; rdb_write_field_name("E"); rdb_write_integer(event->type); rdb_write_integer(event->delay); character_pointer_write(event->character); object_pointer_write(event->object); rdb_write_integer(event->drug); rdb_write_integer(event->psy_power); rdb_write_integer(event->effect); rdb_write_integer(event->power); for (i = 0; i < MAX_STATS; i++) { rdb_write_integer(event->stat_modifier[i]); } } /* * reads an event */ static EVENT * event_read(void) { EVENT *event; int i; event = checked_malloc(sizeof *event); rdb_next_field(); event->type = atoi(rdb_data_token(RDB_NEXT_TOKEN)); event->delay = atoi(rdb_data_token(RDB_NEXT_TOKEN)); event->character = character_pointer_read(); event->object = object_pointer_read(); event->drug = atoi(rdb_data_token(RDB_NEXT_TOKEN)); event->psy_power = atoi(rdb_data_token(RDB_NEXT_TOKEN)); event->effect = atoi(rdb_data_token(RDB_NEXT_TOKEN)); event->power = atoi(rdb_data_token(RDB_NEXT_TOKEN)); for (i = 0; i < MAX_STATS; i++) { event->stat_modifier[i] = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } return event; } /* * writes the save file version */ static void version_write(void) { rdb_write_field_name("V"); rdb_write_string(ENGINE_VERSION); rdb_write_string(scenario_version()); } /* * reads the save file version, and returns true * if the file is compatible */ static bool file_is_compatible(void) { rdb_next_field(); if (strings_equal(ENGINE_VERSION, rdb_data_token(RDB_NEXT_TOKEN)) && strings_equal(scenario_version(), rdb_data_token(RDB_NEXT_TOKEN))) { return true; } return false; } /* * writes the game difficulty */ static void difficulty_write(void) { rdb_write_field_name("D"); rdb_write_integer(game_difficulty()); } /* * reads the game difficulty */ static void difficulty_read(void) { GAME_DIFFICULTY difficulty; rdb_next_field(); difficulty = atoi(rdb_data_token(RDB_NEXT_TOKEN)); game_difficulty_set(difficulty); } /* * writes the game time */ static void time_write(void) { PHASE current_phase; current_phase = get_phase(); rdb_write_field_name("P"); rdb_write_integer(current_phase); } /* * reads the game time */ static void time_read(void) { PHASE current_phase; rdb_next_field(); current_phase = atoi(rdb_data_token(RDB_NEXT_TOKEN)); set_phase(current_phase); } /* * writes the visible area */ static void visible_area_write(void) { area_section_write(get_visible_area()); } /* * reads the visible area */ static void visible_area_read(void) { AREA_SECTION section; area_section_read(§ion); set_visible_area(§ion); } /* * writes the macros */ static void macros_write(void) { int i, j; for (i = 0; i < MAX_MACROS; i++) { KEY_CODE *macro; macro = get_macro(i); rdb_write_field_name("M"); for (j = 0; j < MAX_MACRO_LENGTH; j++) { rdb_write_integer(macro[j]); if (macro[j] == MACRO_TERMINATION_KEY) { break; } } } } /* * reads the macros */ static void macros_read(void) { int i, j; for (i = 0; i < MAX_MACROS; i++) { KEY_CODE macro[MAX_MACRO_LENGTH]; rdb_next_field(); for (j = 0; j < MAX_MACRO_LENGTH; j++) { macro[j] = atoi(rdb_data_token(RDB_NEXT_TOKEN)); if (macro[j] == MACRO_TERMINATION_KEY) { break; } } set_macro(i, macro); } } /* * writes the NPC counter */ static void npc_counter_write(void) { NPC_INDEX npc_index; for (npc_index = npc_box_size() - 1; npc_index >= 0; npc_index--) { const NPC_COUNTER *counter; counter = npc_counter(npc_index); rdb_write_field_name("N"); rdb_write_integer(counter->n_spawned); rdb_write_integer(counter->n_killed); } } /* * reads the NPC counter */ static void npc_counter_read(void) { NPC_INDEX npc_index; for (npc_index = npc_box_size() - 1; npc_index >= 0; npc_index--) { NPC_COUNTER *counter; counter = npc_counter(npc_index); rdb_next_field(); counter->n_spawned = atoi(rdb_data_token(RDB_NEXT_TOKEN)); counter->n_killed = atoi(rdb_data_token(RDB_NEXT_TOKEN)); } } /* * writes a world point */ static void world_point_write(const WORLD_POINT *p) { rdb_write_field_name("W"); rdb_write_integer(p->z); rdb_write_integer(p->y); rdb_write_integer(p->x); } /* * reads a world point */ static void world_point_read(WORLD_POINT *p) { rdb_next_field(); p->z = atoi(rdb_data_token(RDB_NEXT_TOKEN)); p->y = atoi(rdb_data_token(RDB_NEXT_TOKEN)); p->x = atoi(rdb_data_token(RDB_NEXT_TOKEN)); } /* * writes an area point */ static void area_point_write(const AREA_POINT *p) { rdb_write_integer(p->y); rdb_write_integer(p->x); } /* * reads an area point */ static void area_point_read(AREA_POINT *p) { p->y = atoi(rdb_data_token(RDB_NEXT_TOKEN)); p->x = atoi(rdb_data_token(RDB_NEXT_TOKEN)); } /* * writes an area section */ static void area_section_write(const AREA_SECTION *section) { rdb_write_field_name("R"); rdb_write_integer(section->top); rdb_write_integer(section->bottom); rdb_write_integer(section->left); rdb_write_integer(section->right); } /* * reads an area section */ static void area_section_read(AREA_SECTION *section) { rdb_next_field(); section->top = atoi(rdb_data_token(RDB_NEXT_TOKEN)); section->bottom = atoi(rdb_data_token(RDB_NEXT_TOKEN)); section->left = atoi(rdb_data_token(RDB_NEXT_TOKEN)); section->right = atoi(rdb_data_token(RDB_NEXT_TOKEN)); } /* * writes AI data */ static void ai_data_write(const AI_DATA *p) { rdb_write_integer(p->state); rdb_write_integer(p->default_state); rdb_write_integer(p->original_state); rdb_write_integer(p->tactic); area_point_write(&p->target_point); } /* * reads AI data */ static void ai_data_read(AI_DATA *p) { p->state = atoi(rdb_data_token(RDB_NEXT_TOKEN)); p->default_state = atoi(rdb_data_token(RDB_NEXT_TOKEN)); p->original_state = atoi(rdb_data_token(RDB_NEXT_TOKEN)); p->tactic = atoi(rdb_data_token(RDB_NEXT_TOKEN)); area_point_read(&p->target_point); } /* * writes a bool array */ static void bool_array_write(const bool *p, int n_items) { int i; for (i = 0; i < n_items; i++) { rdb_write_integer(p[i]); } } /* * reads a bool array */ static void bool_array_read(bool *p, int n_items) { int i; for (i = 0; i < n_items; i++) { p[i] = (bool)atoi(rdb_data_token(RDB_NEXT_TOKEN)); } }