/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : ORACERES.CPP //Description : Race resource object #include #include #include #include #include #include //---------- #define constant ------------// #define RACE_DB "RACE" #define RACE_NAME_DB "RACENAME" //------- Begin of function RaceRes::RaceRes -----------// RaceRes::RaceRes() { init_flag=0; } //--------- End of function RaceRes::RaceRes -----------// //---------- Begin of function RaceRes::init -----------// // // This function must be called after a map is generated. // void RaceRes::init() { deinit(); //----- open unit bitmap resource file -------// String str; str = DIR_RES; str += "I_RACE.RES"; res_bitmap.init_imported(str, 1); // 1-don't read all into buffer //------- load database information --------// load_race_info(); load_name(); init_flag=1; } //---------- End of function RaceRes::init -----------// //---------- Begin of function RaceRes::deinit -----------// void RaceRes::deinit() { if( init_flag ) { mem_del(race_info_array); mem_del(name_array); mem_del(name_used_array); init_flag=0; } } //---------- End of function RaceRes::deinit -----------// //------- Begin of function RaceRes::load_race_info -------// // // Read in information of RACE.DBF into memory array // void RaceRes::load_race_info() { RaceRec *raceRec; RaceInfo *raceInfo; int i, unitId; long bitmapOffset; Database *dbRace = game_set.open_db(RACE_DB); race_count = (short) dbRace->rec_count(); race_info_array = (RaceInfo*) mem_add( sizeof(RaceInfo)*race_count ); //------ read in race information array -------// memset( race_info_array, 0, sizeof(RaceInfo) * race_count ); for( i=0 ; iread(i+1); raceInfo = race_info_array+i; raceInfo->race_id = i+1; m.rtrim_fld( raceInfo->code, raceRec->code, raceRec->CODE_LEN ); m.rtrim_fld( raceInfo->name, raceRec->name, raceRec->NAME_LEN ); m.rtrim_fld( raceInfo->adjective, raceRec->adjective, raceRec->ADJECTIVE_LEN ); #if(defined(GERMAN) || defined(FRENCH) || defined(SPANISH)) translate.multi_to_win(raceInfo->name, raceInfo->NAME_LEN); translate.multi_to_win(raceInfo->adjective, raceInfo->ADJECTIVE_LEN); #endif memcpy( &bitmapOffset, raceRec->icon_bitmap_ptr, sizeof(long) ); raceInfo->icon_bitmap_ptr = res_bitmap.read_imported(bitmapOffset); err_when( !raceInfo->icon_bitmap_ptr ); for( unitId=1 ; unitId<=MAX_UNIT_TYPE ; unitId++ ) { if( unit_res[unitId]->race_id == i+1 ) { raceInfo->basic_unit_id = unitId; break; } } } } //--------- End of function RaceRes::load_race_info ---------// //------- Begin of function RaceRes::load_name -------// // // Read in information from RACENAME.DBF. // // Note: race_res must be initialized before calling this function. // void RaceRes::load_name() { #define MAX_SINGLE_RACE_NAME 255 // cannot be more than 255 in each name group, as Unit::name_id is an and half of it is for the first name and another half of it is for the last name RaceNameRec *raceNameRec; RaceName *raceName; int i, j; Database *dbRaceName = game_set.open_db(RACE_NAME_DB); name_count = (short) dbRaceName->rec_count(); name_array = (RaceName*) mem_add( sizeof(RaceName)*name_count ); name_used_array = (char*) mem_add( sizeof(name_used_array[0])*name_count ); memset( name_used_array, 0, sizeof(name_used_array[0])*name_count ); //------ read in RaceName info array -------// int raceId=0, isFirstName; for( i=1 ; i<=name_count ; i++ ) { raceNameRec = (RaceNameRec*) dbRaceName->read(i); raceName = name_array+i-1; m.rtrim_fld( raceName->name, raceNameRec->name, raceNameRec->NAME_LEN ); // translate for all language translate.multi_to_win(raceName->name, raceName->NAME_LEN); if( raceName->name[0]=='@' ) { if( raceId ) { if( isFirstName ) race_res[raceId]->first_name_count = i-race_res[raceId]->first_first_name_id; else race_res[raceId]->last_name_count = i-race_res[raceId]->first_last_name_id; err_when( race_res[raceId]->first_name_count > MAX_SINGLE_RACE_NAME ); err_when( race_res[raceId]->last_name_count > MAX_SINGLE_RACE_NAME ); } //----- get the race id. of the following names -----// for( j=1 ; j<=MAX_RACE ; j++ ) { if( strcmp( race_res[j]->code, m.nullify(raceName->name+2, RaceInfo::CODE_LEN) )==0 ) { raceId = j; break; } } err_when( j>MAX_RACE ); //----------------------------------------------// isFirstName = raceName->name[1]=='1'; // whether the following names are first names if( isFirstName ) race_res[raceId]->first_first_name_id = i+1; // next record following the "@RACECODE" is the first name record else race_res[raceId]->first_last_name_id = i+1; // next record following the "@RACECODE" is the first name record } } //------- finish up the last race in the list ------// if( raceId ) { if( isFirstName ) race_res[raceId]->first_name_count = i-race_res[raceId]->first_first_name_id; else race_res[raceId]->last_name_count = i-race_res[raceId]->first_last_name_id; err_when( race_res[raceId]->first_name_count > MAX_SINGLE_RACE_NAME ); err_when( race_res[raceId]->last_name_count > MAX_SINGLE_RACE_NAME ); } } //--------- End of function RaceRes::load_name ---------// //---------- Begin of function RaceRes::is_same_race -----------// // // Return whether the two given race ids are the same. // // This function is called instead of direct in-line comparsion // because it is easier to research all lines that compare races // by keyword searching is_same_race(). // int RaceRes::is_same_race(int raceId1, int raceId2) { return raceId1 == raceId2; } //---------- End of function RaceRes::is_same_race -----------// //----- Start of function RaceInfo::get_new_name_id ------// // // Return an unused name id. and set the used_count of the // first and first name to 1. // WORD RaceInfo::get_new_name_id() { //---------- get the first name ----------// int i; int firstNameId = m.random(first_name_count)+1; for( i=1 ; i<=first_name_count ; i++ ) { if( ++firstNameId > first_name_count ) firstNameId = 1; //--- try to get an unused first name -----// //--- if all names have been used (when i>first_name_count), use the first selected random name id. --// if( !race_res.name_used_array[first_first_name_id+firstNameId-2] ) break; } int nameRecno = first_first_name_id+firstNameId-1; err_when( nameRecno < 1 || nameRecno > race_res.name_count ); race_res.name_used_array[nameRecno-1]++; //---------- get the last name ----------// int lastNameId; if( last_name_count==0 ) // if there is no last name for this race, add Roman letter as the last name { lastNameId = race_res.name_used_array[first_first_name_id+firstNameId-2]; } else // this race has last names { lastNameId = m.random(last_name_count)+1; for( i=1 ; i<=last_name_count ; i++ ) { if( ++lastNameId > last_name_count ) lastNameId = 1; //--- try to get an unused last name -----// //--- if all names have been used, use the first selected random name id. --// if( !race_res.name_used_array[first_last_name_id+lastNameId-2] ) break; } nameRecno = first_last_name_id+lastNameId-1; err_when( nameRecno < 1 || nameRecno > race_res.name_count ); race_res.name_used_array[nameRecno-1]++; } //--- nameId is a combination of first & last name id. ----// err_when( firstNameId < 1 || firstNameId > first_name_count ); err_when( last_name_count>0 && (lastNameId < 1 || lastNameId > last_name_count) ); return (firstNameId<<8) + lastNameId; } //------ End of function RaceInfo::get_new_name_id -------// //----- Start of function RaceInfo::free_name_id ------// // // Free an used name id. // // Unit names are freed when they settle into a town. // But unit names are not freed when they are killed. // void RaceInfo::free_name_id(WORD nameId) { err_when( !nameId ); int firstNameId = (nameId>>8); int nameRecno = first_first_name_id+firstNameId-1; err_when( firstNameId < 1 || firstNameId > first_name_count ); err_when( nameRecno < 1 || nameRecno > race_res.name_count ); race_res.name_used_array[nameRecno-1]--; err_when( race_res.name_used_array[nameRecno-1] < 0 ); if( last_name_count > 0 ) // some races do not have last names { int lastNameId = (nameId&0xFF); int nameRecno = first_last_name_id+lastNameId-1; err_when( lastNameId < 1 || lastNameId > last_name_count ); err_when( nameRecno < 1 || nameRecno > race_res.name_count ); race_res.name_used_array[nameRecno-1]--; err_when( race_res.name_used_array[nameRecno-1] < 0 ); } } //------ End of function RaceInfo::free_name_id -------// //----- Start of function RaceInfo::use_name_id ------// // // Claim the use a specific name id. // void RaceInfo::use_name_id(WORD nameId) { int firstNameId = (nameId>>8); int nameRecno = first_first_name_id+firstNameId-1; err_when( firstNameId < 1 || firstNameId > first_name_count ); err_when( nameRecno < 1 || nameRecno > race_res.name_count ); race_res.name_used_array[nameRecno-1]++; if( last_name_count > 0 ) // some races do not have last names { int lastNameId = (nameId&0xFF); int nameRecno = first_last_name_id+lastNameId-1; err_when( lastNameId < 1 || lastNameId > last_name_count ); err_when( nameRecno < 1 || nameRecno > race_res.name_count ); race_res.name_used_array[nameRecno-1]++; } } //------ End of function RaceInfo::use_name_id -------// //-------- Start of function RaceInfo::get_name -------------// // // nameId - higher byte - first name id, lower byte - last name id. // [int] nameType - 0-full name, 1-first name only, 2-last name only // char* RaceInfo::get_name(WORD nameId, int nameType) { static String str; if( nameId==0 ) { return ""; } else { if( nameType != 2 ) // 2-is for last name only { int firstNameId = (nameId>>8); err_when( firstNameId > first_name_count ); int nameRecno = first_first_name_id+firstNameId-1; err_when( nameRecno < 1 || nameRecno > race_res.name_count ); str = race_res.name_array[nameRecno-1].name; if( nameType==1 ) // first name only return str; } else { if( last_name_count==0 ) // if this race does not have last name return ""; str = ""; } //--------- last name ----------// int lastNameId = (nameId&0xFF); if( last_name_count==0 ) // if there is no last name for this race { if( lastNameId > 1 ) // no need to display roman letter "I" for the first one { if( str.len() > 0 ) str += " "; str += m.roman_number(lastNameId); } } else { err_when( lastNameId > last_name_count ); int nameRecno = first_last_name_id+lastNameId-1; err_when( nameRecno < 1 || nameRecno > race_res.name_count ); if( str.len() > 0 ) str += " "; str += race_res.name_array[nameRecno-1].name; } return str; } } //--------- End of function RaceInfo::get_name ---------------// //-------- Start of function RaceInfo::get_single_name -------------// // // Return a single word name. If there are last names for this race, // return the last name, otherwise, return the first name. // // nameId - higher byte - first name id, lower byte - last name id. // char* RaceInfo::get_single_name(WORD nameId) { switch( race_id ) { case RACE_NORMAN: case RACE_VIKING: #if (MAX_RACE >= 10) case RACE_INDIAN: case RACE_ZULU: #endif return get_name(nameId, 1); // 1-first name only case RACE_CHINESE: case RACE_JAPANESE: return get_name(nameId, 2); // 2-last name only default: return get_name(nameId); // the whole name } } //--------- End of function RaceInfo::get_single_name ---------------// //---------- Begin of function RaceRes::operator[] -----------// RaceInfo* RaceRes::operator[](int raceId) { err_if( raceId<1 || raceId>race_count ) err_now( "RaceRes::operator[]" ); return race_info_array+raceId-1; } //------------ End of function RaceRes::operator[] -----------//