/* * 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: DataFile * Description: - */ #define Uses_Ui #define Uses_ProgramManager #define Uses_Util #define Uses_Equipment #define Uses_Career #define Uses_Race #define Uses_Terrain #define Uses_Object #define Uses_Stats #define Uses_Faction #define Uses_Perks #define Uses_Inventory #define Uses_Npc #define Uses_Character #define Uses_Stats #define Uses_Psychic #define Uses_Options #define Uses_World #define Uses_Perception #define Uses_Scenario #include "mheader.h" #include "rdb.h" #include "datafile.h" /* * config files */ #define FILE_KEYBINDINGS "keys.rdb" #define FILE_OPTIONS "options.rdb" /* * scenario info file */ #define FILE_SCENARIO_INFO "scenario.rdb" /* * world file */ #define FILE_WORLD "world.rdb" /* * race file */ #define FILE_RACE "race.rdb" /* * description files */ #define FILE_PSY_POWERS "powers.rdb" #define FILE_PERKS "perks.rdb" #define FILE_CHARACTER_FLAGS "charflag.rdb" #define FILE_OBJECT_ATTRIBUTES "ob_attr.rdb" #define FILE_TERRAIN_ATTRIBUTES "tr_attr.rdb" /* * psychic bolts file */ #define FILE_PSYCHIC_BOLTS "psybolts.rdb" static char * data_file_entry_description(char *, const char *); static bool load_scenario_info_file(void); static void load_race_file(void); static void load_terrain_files(void); static void load_terrain_file(void); static void load_object_files(void); static void load_object_file(void); static void load_career_files(void); static void load_career_file(void); static void load_npc_files(void); static void load_npc_file(void); static void load_npc_pp(CHARACTER *); static void load_world_file(void); static void read_symbol_field(SYMBOL *); static void read_dynamic_colour_field(DYNAMIC_COLOUR *); static void read_world_point_field(WORLD_POINT *); static void read_stat_field(CHARACTER *, const char *); static void read_firing_mode_field(OBJECT_DATA *); static void read_dice_roll_field(DICE_ROLL *); static void read_direction_field(DIRECTION *); static OBJECT * read_object_field(void); static void read_career_field(CHARACTER *); static void read_description_field(char *, const char *); static void read_key_field(KEY_CODE *); static void read_option_value_field(OPTION_VALUE *); static void read_boolean_field(bool *); static void read_ai_state_field(CHARACTER *); static void read_gender_field(GENDER *); static void read_name_field(char *, unsigned int); static void read_numerus_field(NUMERUS *); static void read_career_exit_field(CAREER *, CAREER_EXIT_INDEX); static void read_world_map_field(WORLD_POINT *); /* * the path of the currently processed file */ static char DataPath[FILE_PATH_SIZE]; /* * sets the data path */ void set_data_path(PROGRAM_DIRECTORY directory, const char *file_name) { get_file_path(DataPath, directory, file_name); } /* * returns the data path */ const char * data_path(void) { return DataPath; } /* * loads the options file */ void load_options(void) { set_data_path(DIR_CONFIG, FILE_OPTIONS); rdb_open(data_path(), RDB_READ); while (rdb_next_field()) { const char *field_name; OPTION_VALUE option_value; field_name = rdb_field_name(); read_option_value_field(&option_value); if (strings_equal(field_name, "FULLSCREEN")) { option_set_value(OPT_FULLSCREEN, option_value ); } else if (strings_equal(field_name, "BRIGHTNESS")) { option_set_value(OPT_BRIGHTNESS, option_value ); } else if (strings_equal(field_name, "CENTER_ON_PLAYER")) { option_set_value(OPT_CENTER_ON_PLAYER, option_value ); } else { die("*** CORE ERROR *** invalid field name: " \ "%s (%s)", field_name, data_path() ); } } rdb_close(); } /* * loads the keybindings */ void load_keybindings(void) { COMMAND command = CM_NIL; set_data_path(DIR_CONFIG, FILE_KEYBINDINGS); rdb_open(data_path(), RDB_READ); while (rdb_next_field()) { const char *field_name; field_name = rdb_field_name(); if (strings_equal(field_name, "COMMAND")) { command = name_to_command( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "KEY")) { KEY_CODE key; read_key_field(&key); set_command_key(command, key); } else { die("*** CORE ERROR *** invalid field " \ "name: %s (%s)", field_name, data_path() ); } } rdb_close(); } /* * loads the scenario data files */ void load_scenario_files(void) { if (!load_scenario_info_file()) { return; } load_race_file(); load_terrain_files(); load_object_files(); load_career_files(); load_npc_files(); load_world_file(); } /* * returns the description of a character flag */ char * data_file_character_flag_description(char *description, CHARACTER_FLAG flag ) { clear_string(description); set_data_path(DIR_DESCRIPTIONS, FILE_CHARACTER_FLAGS); data_file_entry_description(description, character_flag_name(flag) ); return description; } /* * returns the description of an object attribute */ char * data_file_object_attribute_description(char *description, OBJECT_ATTRIBUTE attribute ) { clear_string(description); set_data_path(DIR_DESCRIPTIONS, FILE_OBJECT_ATTRIBUTES); data_file_entry_description(description, object_attribute_name(attribute) ); return description; } /* * returns the description of a terrain attribute */ char * data_file_terrain_attribute_description(char *description, TERRAIN_ATTRIBUTE attribute ) { clear_string(description); set_data_path(DIR_DESCRIPTIONS, FILE_TERRAIN_ATTRIBUTES); data_file_entry_description(description, terrain_attribute_name(attribute) ); return description; } /* * returns the description of a psychic power */ char * data_file_psy_power_description(char *description, PSY_POWER power) { clear_string(description); set_data_path(DIR_DESCRIPTIONS, FILE_PSY_POWERS); data_file_entry_description(description, psy_power_name(power)); return description; } /* * returns the description of a perk */ char * data_file_perk_description(char *description, PERK perk) { clear_string(description); set_data_path(DIR_DESCRIPTIONS, FILE_PERKS); data_file_entry_description(description, perk_name(perk)); return description; } /* * returns the description of a data file entry */ static char * data_file_entry_description(char *description, const char *entry_name ) { bool entry_reached = false; rdb_open(data_path(), RDB_READ); clear_string(description); while (rdb_next_field()) { const char *field_name; field_name = rdb_field_name(); if (strings_equal(field_name, "NAME")) { if (entry_reached) break; if (strings_equal(rdb_data_token(RDB_NEXT_TOKEN), entry_name)) { entry_reached = true; } continue; } if (entry_reached && strings_equal(field_name, "DESCRIPTION")) { read_description_field(description, entry_name); } } rdb_close(); return description; } /* * loads the scenario info file */ static bool load_scenario_info_file(void) { set_data_path(DIR_INFO, FILE_SCENARIO_INFO); if (!file_exists(data_path())) return false; rdb_open(data_path(), RDB_READ); while (rdb_next_field()) { const char *field_name; field_name = rdb_field_name(); if (strings_equal(field_name, "NAME")) { strcpy(scenario_name(), rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "VERSION")) { strcpy(scenario_version(), rdb_data_token(RDB_NEXT_TOKEN) ); } else { die("*** CORE ERROR *** invalid field name: " \ "%s (%s)", field_name, data_path() ); } } rdb_close(); return true; } /* * loads the race file */ static void load_race_file(void) { RACE *race; race = player_race(); set_data_path(DIR_RACE, FILE_RACE); rdb_open(data_path(), RDB_READ); while (rdb_next_field()) { const char *field_name; field_name = rdb_field_name(); if (strings_equal(field_name, "SYMBOL")) { read_symbol_field(&race->symbol); strcpy(world()->name, rdb_data_token(RDB_NEXT_TOKEN)); }else if (is_short_stat_name(field_name)) { STAT i; i = name_to_stat(field_name, true); read_dice_roll_field(&race->profile[i]); } else { die("*** CORE ERROR *** invalid field name: %s (%s)", field_name, data_path() ); } } rdb_close(); } /* * loads the terrain files */ static void load_terrain_files(void) { LIST *file_list; LIST_NODE *node; file_list = data_files(DIR_TERRAIN); for (node = file_list->head; node != NULL; node = node->next) { const char *file_name; file_name = (const char *)node->data; set_data_path(DIR_TERRAIN, file_name); load_terrain_file(); } list_free_with(file_list, free); terrain_box_optimize(); } /* * loads a terrain file */ static void load_terrain_file(void) { TERRAIN_DATA *terrain_data = NULL; rdb_open(data_path(), RDB_READ); while (rdb_next_field()) { const char *field_name; field_name = rdb_field_name(); if (strings_equal(field_name, "NAME")) { terrain_data = terrain_box_new_terrain(); read_name_field(terrain_data->name, TERRAIN_NAME_SIZE ); } else if (strings_equal(field_name, "SYMBOL")) { read_symbol_field(&terrain_data->symbol); } else if (strings_equal(field_name, "COLOUR")) { read_dynamic_colour_field(&terrain_data->colour); } else if (strings_equal(field_name, "ATTRIBUTE")) { TERRAIN_ATTRIBUTE attribute; attribute = name_to_terrain_attribute( rdb_data_token(RDB_NEXT_TOKEN) ); terrain_data->attribute[attribute] = true; } else if (strings_equal(field_name, "DESCRIPTION")) { read_description_field(terrain_data->description, terrain_data->name ); } else { die("*** CORE ERROR *** invalid field name: " \ "%s (%s)", field_name, data_path() ); } } rdb_close(); } /* * loads the object files */ static void load_object_files(void) { LIST *file_list; LIST_NODE *node; file_list = data_files(DIR_OBJECTS); for (node = file_list->head; node != NULL; node = node->next) { const char *file_name; file_name = (const char *)node->data; set_data_path(DIR_OBJECTS, file_name); load_object_file(); } list_free_with(file_list, free); set_data_path(DIR_PSYCHIC_BOLTS, FILE_PSYCHIC_BOLTS); load_object_file(); object_box_optimize(); } /* * loads an object file */ static void load_object_file(void) { OBJECT_DATA *object_data = NULL; rdb_open(data_path(), RDB_READ); while (rdb_next_field()) { const char *field_name; field_name = rdb_field_name(); if (strings_equal(field_name, "NAME")) { object_data = object_box_new_object(); read_name_field(object_data->name, OBJECT_NAME_SIZE ); } else if (strings_equal(field_name, "NUMERUS")) { read_numerus_field(&object_data->numerus); } else if (strings_equal(field_name, "SYMBOL")) { read_symbol_field(&object_data->symbol); } else if (strings_equal(field_name, "COLOUR")) { read_dynamic_colour_field(&object_data->colour); } else if (strings_equal(field_name, "TYPE")) { object_data->type = name_to_object_type( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "SUBTYPE")) { object_data->subtype = name_to_object_subtype( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "CONDITION")) { object_data->condition_max = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "VALUE")) { object_data->value = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "WEIGHT")) { object_data->weight = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "DAMAGE")) { read_dice_roll_field(&object_data->damage); } else if (strings_equal(field_name, "ARMOUR_VALUE")) { object_data->armour_value = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "ACCURACY")) { object_data->firing_mode.accuracy = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "SHOTS")) { object_data->charge_max = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "FIRING_MODE")) { read_firing_mode_field(object_data); } else if (strings_equal(field_name, "RELOAD")) { object_data->reload = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "ATTRIBUTE")) { OBJECT_ATTRIBUTE attribute; attribute = name_to_object_attribute( rdb_data_token(RDB_NEXT_TOKEN) ); object_data->attribute[attribute] = true; } else if (strings_equal(field_name, "REACH")) { object_data->reach = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "PARRY_PENALTY")) { object_data->parry_penalty = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "DESCRIPTION")) { read_description_field(object_data->description, object_data->name ); } else { die("*** CORE ERROR *** invalid field name: %s (%s)", field_name, data_path() ); } } rdb_close(); } /* * loads the career files */ static void load_career_files(void) { LIST *file_list; LIST_NODE *node; file_list = data_files(DIR_CAREERS); for (node = file_list->head; node != NULL; node = node->next) { const char *file_name; file_name = (const char *)node->data; set_data_path(DIR_CAREERS, file_name); load_career_file(); } list_free_with(file_list, free); career_box_optimize(); #if defined(DEBUG) career_box_validate(); #endif } /* * loads a career file */ static void load_career_file(void) { CAREER *career = NULL; CAREER_EXIT_INDEX career_exit_index = 0; rdb_open(data_path(), RDB_READ); while (rdb_next_field()) { const char *field_name; field_name = rdb_field_name(); if (strings_equal(field_name, "NAME")) { career = career_box_new_career(); career_exit_index = 0; read_name_field(career->name, CAREER_NAME_SIZE ); } else if (strings_equal(field_name, "TYPE")) { career->type = name_to_career_type( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "COLOUR")) { career->colour = name_to_colour( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (is_short_stat_name(field_name)) { STAT i; i = name_to_stat(field_name, true); career->max_stat_advance[i] = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "PERK")) { PERK perk; perk = name_to_perk( rdb_data_token(RDB_NEXT_TOKEN) ); career->perk[perk] = true; } else if (strings_equal(field_name, "OBJECT")) { OBJECT *object; object = read_object_field(); list_add(career->trappings, object); } else if (strings_equal(field_name, "EXIT")) { read_career_exit_field(career, career_exit_index); ++career_exit_index; } else if (strings_equal(field_name, "DESCRIPTION")) { read_description_field(career->description, career->name ); } else { die("*** CORE ERROR *** invalid field name: %s (%s)", field_name, data_path() ); } } rdb_close(); } /* * loads the NPC files */ static void load_npc_files(void) { LIST *file_list; LIST_NODE *node; file_list = data_files(DIR_NPCS); for (node = file_list->head; node != NULL; node = node->next) { const char *file_name; file_name = (const char *)node->data; set_data_path(DIR_NPCS, file_name); load_npc_file(); } list_free_with(file_list, free); npc_box_optimize(); npc_counter_init(); } /* * loads a NPC file */ static void load_npc_file(void) { CHARACTER *npc = NULL; rdb_open(data_path(), RDB_READ); while (rdb_next_field()) { const char *field_name; field_name = rdb_field_name(); if (strings_equal(field_name, "NAME")) { if (npc != NULL) { load_npc_pp(npc); } npc = npc_box_new_npc(); read_name_field(npc->name, CHARACTER_NAME_SIZE ); } else if (strings_equal(field_name, "NUMERUS")) { read_numerus_field(&npc->numerus); } else if (strings_equal(field_name, "CAREER")) { read_career_field(npc); } else if (strings_equal(field_name, "HOSTILE")) { read_boolean_field(&npc->is_hostile); } else if (strings_equal(field_name, "GENDER")) { read_gender_field(&npc->gender); } else if (strings_equal(field_name, "SYMBOL")) { read_symbol_field(&npc->symbol); } else if (strings_equal(field_name, "COLOUR")) { npc->colour = name_to_colour( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (is_short_stat_name(field_name)) { read_stat_field(npc, field_name); } else if (strings_equal(field_name, "OBJECT")) { OBJECT *object; object = read_object_field(); inventory_add(npc, object); } else if (strings_equal(field_name, "PERK")) { PERK perk; perk = name_to_perk( rdb_data_token(RDB_NEXT_TOKEN) ); give_perk(npc, perk); } else if (strings_equal(field_name, "PSYCHIC_POWER")) { PSY_POWER power; power = name_to_psy_power( rdb_data_token(RDB_NEXT_TOKEN) ); npc->psy_power[power] = true; } else if (strings_equal(field_name, "STATUS")) { CHARACTER_FLAG flag; flag = name_to_character_flag( rdb_data_token(RDB_NEXT_TOKEN) ); character_set_flag(npc, flag); } else if (strings_equal(field_name, "AI_DEFAULT_STATE")) { read_ai_state_field(npc); } else if (strings_equal(field_name, "SCRIPT")) { strcpy(npc->script, rdb_data_token(RDB_NEXT_TOKEN)); } else if (strings_equal(field_name, "DESCRIPTION")) { read_description_field(npc->description, npc->name); } else { die("*** CORE ERROR *** invalid field name: %s (%s)", field_name, data_path() ); } } if (npc != NULL) { load_npc_pp(npc); } rdb_close(); } /* * NPC loading post-processor */ static void load_npc_pp(CHARACTER *npc) { equip_objects(npc); if (npc->perk[PK_STEALTH]) { activate_stealth(npc); } } /* * loads the world file */ static void load_world_file(void) { WORLD_POINT current_position = {0, 0, 0}; WORLD_TILE_DATA *tile_data = NULL; bool world_name_read = false; set_data_path(DIR_WORLD, FILE_WORLD); rdb_open(data_path(), RDB_READ); while (rdb_next_field()) { const char *field_name; field_name = rdb_field_name(); if (strings_equal(field_name, "NAME")) { if (!world_name_read) { strcpy(world()->name, rdb_data_token(RDB_NEXT_TOKEN) ); world_name_read = true; continue; } strcpy(tile_data->name, rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "DESCRIPTION")) { strcat(world()->description, rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "STARTING_POSITION")) { read_world_point_field(&world()->starting_position); } else if (strings_equal(field_name, "STARTING_DIRECTION")) { read_direction_field(&world()->starting_direction); } else if (strings_equal(field_name, "TILE")) { tile_data = world_tile_box_new_tile(); tile_data->symbol = rdb_data_token(RDB_NEXT_TOKEN)[0]; } else if (strings_equal(field_name, "SYMBOL")) { tile_data->screen_symbol = rdb_data_token(RDB_NEXT_TOKEN)[0]; } else if (strings_equal(field_name, "COLOUR")) { tile_data->colour = name_to_colour( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "N_LEVELS")) { tile_data->n_levels = atoi( rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "SCRIPT")) { strcpy(tile_data->script, rdb_data_token(RDB_NEXT_TOKEN) ); } else if (strings_equal(field_name, "M")) { read_world_map_field(¤t_position); } else { die("*** CORE ERROR *** invalid field name: %s (%s)", field_name, data_path() ); } } rdb_close(); world_tile_box_optimize(); } /* * reads symbol field data */ static void read_symbol_field(SYMBOL *symbol) { const char *data_token; data_token = rdb_data_token(0); if (data_token[1] != '\0') { *symbol = name_to_symbol(data_token); } else { *symbol = data_token[0]; } } /* * reads dynamic colour field data */ static void read_dynamic_colour_field(DYNAMIC_COLOUR *colour) { colour->primary = name_to_colour(rdb_data_token(0)); if (rdb_optional_data_token(1) == NULL) { colour->secondary = C_NIL; colour->frequency = 0; return; } colour->secondary = name_to_colour(rdb_data_token(1)); colour->frequency = atoi(rdb_data_token(2)); } /* * reads world point field data */ static void read_world_point_field(WORLD_POINT *p) { 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)); } /* * reads stat field data */ static void read_stat_field(CHARACTER *character, const char *field_name) { STAT i; i = name_to_stat(field_name, true); character->stat[i].current = character->stat[i].total = atoi(rdb_data_token(0)); if (rdb_optional_data_token(1) != NULL) { character->stat[i].advance = atoi(rdb_data_token(1)); } } /* * reads firing mode field data */ static void read_firing_mode_field(OBJECT_DATA *object_data) { FIRING_MODE firing_mode; firing_mode = name_to_firing_mode(rdb_data_token(RDB_NEXT_TOKEN)); object_data->firing_mode.has[firing_mode] = true; if (firing_mode == FMODE_S) { return; } if (firing_mode == FMODE_SA) { object_data->firing_mode.min_sa_shots = atoi(rdb_data_token(RDB_NEXT_TOKEN)); object_data->firing_mode.max_sa_shots = atoi(rdb_data_token(RDB_NEXT_TOKEN)); } else if (firing_mode == FMODE_A) { object_data->firing_mode.a_shots = atoi(rdb_data_token(RDB_NEXT_TOKEN)); } } /* * reads dice roll field data */ static void read_dice_roll_field(DICE_ROLL *dice_roll) { dice_roll->n_dice = atoi(rdb_data_token(RDB_NEXT_TOKEN)); dice_roll->n_sides = atoi(rdb_data_token(RDB_NEXT_TOKEN)); if (rdb_optional_data_token(2) == NULL) { dice_roll->modifier = 0; return; } dice_roll->modifier = atoi(rdb_data_token(2)); } /* * reads direction field data */ static void read_direction_field(DIRECTION *direction) { *direction = name_to_direction(rdb_data_token(RDB_NEXT_TOKEN)); } /* * reads object field data */ static OBJECT * read_object_field(void) { OBJECT *object; object = object_create(rdb_data_token(0)); if (rdb_optional_data_token(1) == NULL) { return object; } object->charge = atoi(rdb_data_token(1)); return object; } /* * reads career field data */ static void read_career_field(CHARACTER *character) { CAREER_INDEX career_index; career_index = name_to_career_index( rdb_data_token(RDB_NEXT_TOKEN) ); career_set(character, career_index); } /* * reads description field data */ static void read_description_field(char *description, const char *entry_name) { #if defined(DEBUG) char text_buffer[TEXT_BUFFER_SIZE]; strcpy(text_buffer, description); strcat(text_buffer, rdb_data_token(RDB_NEXT_TOKEN)); if (strlen(text_buffer) >= DESCRIPTION_SIZE) { die("*** CORE ERROR *** description of %s in %s "\ "is too long (limit: %d characters)", entry_name, data_path(), DESCRIPTION_SIZE - 1 ); } strcpy(description, text_buffer); #else strcat(description, rdb_data_token(RDB_NEXT_TOKEN)); #endif } /* * reads key field data */ static void read_key_field(KEY_CODE *key) { *key = name_to_key_code(rdb_data_token(RDB_NEXT_TOKEN)); } /* * reads option value field data */ static void read_option_value_field(OPTION_VALUE *option_value) { *option_value = (OPTION_VALUE)( atoi(rdb_data_token(RDB_NEXT_TOKEN)) ); } /* * reads boolean field data */ static void read_boolean_field(bool *data) { if (strings_equal(rdb_data_token(0), "Yes")) { *data = true; } else if (strings_equal(rdb_data_token(0), "No")) { *data = false; } else { die("*** CORE ERROR *** invalid data in " \ "boolean field: %s", rdb_data_token(0) ); } } /* * reads AI state field data */ static void read_ai_state_field(CHARACTER *character) { if (strings_equal(rdb_data_token(0), "Wait")) { character->ai.state = character->ai.default_state = character->ai.original_state = AI_STATE_WAIT; } else { die("*** CORE ERROR *** invalid data in " \ "AI state field: %s", rdb_data_token(0) ); } } /* * reads gender field data */ static void read_gender_field(GENDER *gender) { switch (rdb_data_token(0)[0]) { case 'M': *gender = GENDER_MALE; break; case 'F': *gender = GENDER_FEMALE; break; case 'N': *gender = GENDER_NEUTER; break; default: die("*** CORE ERROR *** invalid data in gender field: %c", rdb_data_token(0)[0] ); } } /* * reads name field data */ static void read_name_field(char *name, unsigned int n) { if (strlen(rdb_data_token(0)) < n) { strcpy(name, rdb_data_token(0)); return; } die("*** CORE ERROR *** name too long: %s " \ "(limit: %d characters)", rdb_data_token(0), n - 1 ); } /* * reads numerus field data */ static void read_numerus_field(NUMERUS *numerus) { const char *string; string = rdb_data_token(0); if (strings_equal(string, "Singular")) { *numerus = NUMERUS_SINGULAR; } else if (strings_equal(string, "Plural")) { *numerus = NUMERUS_PLURAL; } else { die("*** CORE ERROR *** invalid numerus field value"); } } /* * reads career exit field data */ static void read_career_exit_field(CAREER *career, CAREER_EXIT_INDEX career_exit_index ) { const char *career_name; if (career_exit_index >= MAX_CAREER_EXITS) { die("*** CORE ERROR *** The career %s has " "too many exits", career->name); } career_name = rdb_data_token(RDB_NEXT_TOKEN); strcpy(career->exit[career_exit_index], career_name); } /* * reads world map field data */ static void read_world_map_field(WORLD_POINT *current_position) { const char *map_line; map_line = rdb_data_token(RDB_NEXT_TOKEN); current_position->x = 0; while (*map_line != '\0') { WORLD_TILE *tile; tile = world_tile(current_position); *tile = symbol_to_world_tile(*map_line); ++map_line; ++current_position->x; } ++current_position->y; }