/* * 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 : OTOWNRES.CPP //Description : Town resource object #include #include #include #include #include #include //---------- define constant ------------// #define TOWN_LAYOUT_DB "TOWNLAY" #define TOWN_SLOT_DB "TOWNSLOT" #define TOWN_BUILD_TYPE_DB "TOWNBTYP" #define TOWN_BUILD_DB "TOWNBULD" #define TOWN_NAME_DB "TOWNNAME" //------- Begin of function TownRes::TownRes -----------// TownRes::TownRes() { init_flag=0; } //--------- End of function TownRes::TownRes -----------// //---------- Begin of function TownRes::init -----------// // // This function must be called after a map is generated. // void TownRes::init() { deinit(); //----- open town material bitmap resource file -------// String str; str = DIR_RES; str += "I_TOWN.RES"; res_bitmap.init_imported(str,1); // 1-read all into buffer //------- load database information --------// load_town_slot(); // load_town_slot() must be called first before load_town_layout(), as load_town_layout() accesses town_slot_array load_town_layout(); load_town_build_type(); load_town_build(); load_town_name(); init_flag=1; } //---------- End of function TownRes::init -----------// //---------- Begin of function TownRes::deinit -----------// void TownRes::deinit() { if( init_flag ) { mem_del(town_layout_array); mem_del(town_slot_array); mem_del(town_build_array); mem_del(town_build_type_array); mem_del(town_name_array); mem_del(town_name_used_array); res_bitmap.deinit(); init_flag=0; } } //---------- End of function TownRes::deinit -----------// //------- Begin of function TownRes::load_town_layout -------// // // Read in information from TOWNLAY.DBF. // void TownRes::load_town_layout() { TownLayoutRec *townLayoutRec; TownLayout *townLayout; TownSlot *townSlot; int i, j; Database *dbTownLayout = game_set.open_db(TOWN_LAYOUT_DB); town_layout_count = (short) dbTownLayout->rec_count(); town_layout_array = (TownLayout*) mem_add( sizeof(TownLayout)*town_layout_count ); //------ read in town layout info array -------// memset( town_layout_array, 0, sizeof(TownLayout) * town_layout_count ); for( i=0 ; iread(i+1); townLayout = town_layout_array+i; townLayout->first_slot_recno = m.atoi(townLayoutRec->first_slot, TownLayoutRec::FIRST_SLOT_LEN); townLayout->slot_count = m.atoi(townLayoutRec->slot_count, TownLayoutRec::SLOT_COUNT_LEN); // ###### begin Gilbert 9/9 ########// // townLayout->ground_bitmap_ptr = image_spict.get_ptr( m.nullify(townLayoutRec->ground_name, TownLayoutRec::GROUND_NAME_LEN) ); townLayout->ground_bitmap_ptr = image_tpict.get_ptr( m.nullify(townLayoutRec->ground_name, TownLayoutRec::GROUND_NAME_LEN) ); // ###### end Gilbert 9/9 ########// err_if( townLayout->slot_count > MAX_TOWN_LAYOUT_SLOT ) err_now( "Error: MAX_TOWN_LAYOUT_SLOT limit exceeded." ); //----- calculate min_population & max_population -----// townSlot = town_slot_array+townLayout->first_slot_recno-1; for( j=0 ; jslot_count ; j++, townSlot++ ) { if( townSlot->build_type==TOWN_OBJECT_HOUSE ) // if there is a building in this slot townLayout->build_count++; } } } //--------- End of function TownRes::load_town_layout ---------// //------- Begin of function TownRes::load_town_slot -------// // // Read in information from TOWNSLOT.DBF. // void TownRes::load_town_slot() { TownSlotRec *townSlotRec; TownSlot *townSlot; int i; Database *dbTownSlot = game_set.open_db(TOWN_SLOT_DB); town_slot_count = (short) dbTownSlot->rec_count(); town_slot_array = (TownSlot*) mem_add( sizeof(TownSlot)*town_slot_count ); //------ read in town slot info array -------// memset( town_slot_array, 0, sizeof(TownSlot) * town_slot_count ); for( i=0 ; iread(i+1); townSlot = town_slot_array+i; townSlot->base_x = m.atoi(townSlotRec->base_x, TownSlotRec::POS_LEN); townSlot->base_y = m.atoi(townSlotRec->base_y, TownSlotRec::POS_LEN); townSlot->build_type = m.atoi(townSlotRec->type_id, TownSlotRec::TYPE_ID_LEN); townSlot->build_code = m.atoi(townSlotRec->build_code, TownSlotRec::BUILD_CODE_LEN); err_when( townSlot->build_type == TOWN_OBJECT_FARM && (townSlot->build_code < 1 || townSlot->build_code > 9) ); } } //--------- End of function TownRes::load_town_slot ---------// //------- Begin of function TownRes::load_town_build_type -------// // // Read in information from TOWNBTYP.DBF. // void TownRes::load_town_build_type() { TownBuildTypeRec *buildTypeRec; TownBuildType *buildType; int i; Database *dbTownBuildType = game_set.open_db(TOWN_BUILD_TYPE_DB); town_build_type_count = (short) dbTownBuildType->rec_count(); town_build_type_array = (TownBuildType*) mem_add( sizeof(TownBuildType)*town_build_type_count ); //------ read in TownBuildType info array -------// memset( town_build_type_array, 0, sizeof(TownBuildType) * town_build_type_count ); for( i=0 ; iread(i+1); buildType = town_build_type_array+i; buildType->first_build_recno = m.atoi(buildTypeRec->first_build, TownBuildTypeRec::FIRST_BUILD_LEN); buildType->build_count = m.atoi(buildTypeRec->build_count, TownBuildTypeRec::BUILD_COUNT_LEN); } } //--------- End of function TownRes::load_town_build_type ---------// //------- Begin of function TownRes::load_town_build -------// // // Read in information from TOWNBULD.DBF. // void TownRes::load_town_build() { TownBuildRec *townBuildRec; TownBuild *townBuild; int i; long bitmapOffset; Database *dbTownBuild = game_set.open_db(TOWN_BUILD_DB); town_build_count = (short) dbTownBuild->rec_count(); town_build_array = (TownBuild*) mem_add( sizeof(TownBuild)*town_build_count ); err_when( town_build_count > 255 ); // BYTE is used in TownZone::slot_array[] //------ read in town build info array -------// memset( town_build_array, 0, sizeof(TownBuild) * town_build_count ); for( i=0 ; iread(i+1); townBuild = town_build_array+i; townBuild->build_type = m.atoi(townBuildRec->type_id, TownBuildRec::TYPE_ID_LEN); townBuild->build_code = m.atoi(townBuildRec->build_code, TownBuildRec::BUILD_CODE_LEN); townBuild->race_id = m.atoi(townBuildRec->race_id, TownBuildRec::RACE_ID_LEN); memcpy( &bitmapOffset, townBuildRec->bitmap_ptr, sizeof(long) ); townBuild->bitmap_ptr = res_bitmap.read_imported(bitmapOffset); townBuild->bitmap_width = *((short*)townBuild->bitmap_ptr); townBuild->bitmap_height = *(((short*)townBuild->bitmap_ptr)+1); } } //--------- End of function TownRes::load_town_build ---------// //------- Begin of function TownRes::load_town_name -------// // // Read in information from TOWNNAME.DBF. // // Note: race_res must be initialized before calling this function. // void TownRes::load_town_name() { TownNameRec *townNameRec; TownName *townName; int i; Database *dbTownName = game_set.open_db(TOWN_NAME_DB); town_name_count = dbTownName->rec_count(); town_name_array = (TownName*) mem_add( sizeof(TownName)*town_name_count ); town_name_used_array = (char*) mem_add( sizeof(town_name_used_array[0]) * town_name_count ); // store the used_count separately from town_name_array to faciliate file saving memset( town_name_used_array, 0, sizeof(town_name_used_array[0]) * town_name_count ); //------ read in TownName info array -------// int raceId=0; for( i=1 ; i<=town_name_count ; i++ ) { townNameRec = (TownNameRec*) dbTownName->read(i); townName = town_name_array+i-1; m.rtrim_fld( townName->name, townNameRec->name, townNameRec->NAME_LEN ); if( townName->name[0]=='@' ) // next race { int j; for( j=1 ; j<=MAX_RACE ; j++ ) { if( strcmp( race_res[j]->code, townName->name+1 ) == 0 ) break; } err_when( j > MAX_RACE ); if( raceId ) race_res[raceId]->town_name_count = i-race_res[raceId]->first_town_name_recno; raceId = j; race_res[raceId]->first_town_name_recno = i+1; } } //-- set the town_name_count of the last town in TOWNNAME.DBF --// race_res[raceId]->town_name_count = i-race_res[raceId]->first_town_name_recno; } //--------- End of function TownRes::load_town_name ---------// //---------- Begin of function TownRes::scan_build -----------// // // Set the given slot with a building that fits the given criteria // // slotId - the slot id. of the current town section to be set. // raceId - one of the building selection criteria // (0-any race) // // return : townBuildId - the id. of the town building // int TownRes::scan_build(int slotId, int raceId) { enum { MAX_SCAN_ID = 100 }; TownSlot* townSlot = town_res.get_slot(slotId); TownBuildType* buildType; TownBuild* townBuild; int i, buildRecno, matchCount=0; int scanIdArray[MAX_SCAN_ID]; //---- get the building type of the slot ------// buildType = town_res.get_build_type(townSlot->build_type); err_if( buildType->build_count==0 ) err_here(); //------ scan_build buildings of the specified type ------// buildRecno = buildType->first_build_recno; townBuild = town_res.get_build(buildRecno); // the pointer to the first building of the specified type for( i=buildType->build_count ; i>0 ; i--, townBuild++, buildRecno++ ) { if( townBuild->build_code == townSlot->build_code ) { if( !raceId || townBuild->race_id == raceId ) { scanIdArray[matchCount] = buildRecno; if( ++matchCount >= MAX_SCAN_ID ) break; } } } //--- pick one from those plants that match the criteria ---// if( matchCount > 0 ) { int buildId = scanIdArray[m.random(matchCount)]; #ifdef DEBUG town_res.get_build( buildId ); // get_build() will error if buildId is not valid #endif return buildId; } else return 0; } //---------- End of function TownRes::scan_build -----------// #ifdef DEBUG //---------- Begin of function TownRes::get_layout -----------// TownLayout* TownRes::get_layout(int recNo) { err_if( recNo<1 || recNo>town_layout_count ) err_now( "TownRes::get_layout()" ); return town_layout_array+recNo-1; } //------------ End of function TownRes::get_layout -----------// //---------- Begin of function TownRes::get_slot -----------// TownSlot* TownRes::get_slot(int recNo) { err_if( recNo<1 || recNo>town_slot_count ) err_now( "TownRes::get_slot()" ); return town_slot_array+recNo-1; } //------------ End of function TownRes::get_slot -----------// //---------- Begin of function TownRes::get_build_type -----------// TownBuildType* TownRes::get_build_type(int recNo) { err_if( recNo<1 || recNo>town_build_type_count ) err_now( "TownRes::get_build_type()" ); return town_build_type_array+recNo-1; } //------------ End of function TownRes::get_build_type -----------// //---------- Begin of function TownRes::get_build -----------// TownBuild* TownRes::get_build(int recNo) { err_if( recNo<1 || recNo>town_build_count ) err_now( "TownRes::get_build()" ); return town_build_array+recNo-1; } //------------ End of function TownRes::get_build -----------// #endif //---------- Begin of function TownRes::get_name -----------// char* TownRes::get_name(int recNo) { err_if( recNo<1 || recNo>town_name_count ) err_now( "TownRes::get_name()" ); return town_name_array[recNo-1].name; } //------------ End of function TownRes::get_name -----------// //--------- Begin of function TownRes::get_new_name_id ----------// // int TownRes::get_new_name_id(int raceId) { RaceInfo* raceInfo = race_res[raceId]; err_when( raceInfo->town_name_used_count > raceInfo->town_name_count ); int townNameId; //----- if all town names have been used already -----// //--- scan the town name one by one and pick an unused one ---// if( raceInfo->town_name_used_count == raceInfo->town_name_count ) { int nameId = m.random(raceInfo->town_name_count)+1; // this is the id. of one race only for( int i=raceInfo->town_name_count ; i>0 ; i-- ) { if( ++nameId > raceInfo->town_name_count ) nameId = 1; if( town_name_used_array[raceInfo->first_town_name_recno+nameId-2]==0 ) // -2 is the total of two -1, (one with first_town_name_recno, another with town_name_used_array[] break; } townNameId = raceInfo->first_town_name_recno + nameId - 1; } else { raceInfo->town_name_used_count++; townNameId = raceInfo->first_town_name_recno + raceInfo->town_name_used_count - 1; } err_when( townNameId < 1 || townNameId > town_name_count ); town_name_used_array[townNameId-1]++; return townNameId; } //--------- End of function TownRes::get_new_name_id ----------// //--------- Begin of function TownRes::free_name_id ----------// // // Free an used name id. // void TownRes::free_name_id(int townNameId) { town_name_used_array[townNameId-1]--; err_when( town_name_used_array[townNameId-1] < 0 ); } //--------- End of function TownRes::free_name_id ----------//