/* * 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 : OFIRMA.CPP //Description : Object Firm Array #include #include #include #include #include #include #include #include #include #include #include #include //### begin alex 22/9 ###// #ifdef DEBUG #include static unsigned long last_firm_ai_profile_time = 0L; static unsigned long firm_ai_profile_time = 0L; static unsigned long last_firm_profile_time = 0L; static unsigned long firm_profile_time = 0L; #endif //#### end alex 22/9 ####// //----------- Note ----------------// // // go(), start(), end(), fwd(), bkwd() will affect // the current record no. pointer which will be used by other function // // To process all elements in the array, get(recNo) should be used. // // Because the sizeof different derived Firm objects are quite largely // different, it is better to link in pointer instead of the object // body. // // The DynArrayB contain the pointer to Firm objects. // //---------------------------------// //--------- Begin of function FirmArray::FirmArray ---------// // FirmArray::FirmArray() : DynArrayB(sizeof(Firm*), 50, DEFAULT_REUSE_INTERVAL_DAYS) { } //----------- End of function FirmArray::FirmArray ---------// //--------- Begin of function FirmArray::~FirmArray ---------// // FirmArray::~FirmArray() { deinit(); } //----------- End of function FirmArray::~FirmArray ---------// //--------- Begin of function FirmArray::init ---------// void FirmArray::init() { process_recno = 1; } //---------- End of function FirmArray::init ---------// //--------- Begin of function FirmArray::deinit ---------// // // All firms should be deleted when the system terminated // // Chain : delete nation --> delete firm --> delete job --> delete item // // Some data is corrupted when the some firms still exist when // the system terminated // void FirmArray::deinit() { if( size()==0 ) return; //----------------------------------// int i; for( i=1 ; i<=size() ; i++ ) { if( !firm_array.is_deleted(i) ) firm_array.del_firm(i); } //----------------------------------// zap(); // zap the DynArrayB } //----------- End of function FirmArray::deinit ---------// //--------- Begin of function FirmArray::build_firm ---------// // // build_firm() will be called by Nation and FirmRes when setting up // new firm. // // xLoc = the x location of the firm to be built // yLoc = the y location of the firm to be built // nationRecno = the nation which builds this firm // firmId = firm type id. // [char*] buildCode = the build code of the firm, no need to give if the firm just have one build type // [short] builderRecno = recno of the builder unit // // Return : the record no. of the newly added firm // int FirmArray::build_firm(int xLoc, int yLoc, int nationRecno, int firmId, char* buildCode, short builderRecno) { if( !world.can_build_firm(xLoc, yLoc, firmId) ) return 0; //--------- check if there is enough cash ----------// if( nationRecno ) { FirmInfo* firmInfo = firm_res[firmId]; Nation* nationPtr = nation_array[nationRecno]; if( nationRecno ) { if( nationPtr->cash < firmInfo->setup_cost ) return 0; } } //---------- create and build the firm -------------// int firmRecno = create_firm(firmId); firm_array[firmRecno]->init( xLoc, yLoc, nationRecno, firmId, buildCode, builderRecno); // Firm::init() will set world matrix, it will use Firm::firm_recno to set the location cargo //------ pay the land cost to the nation that owns the land ------// if( nationRecno ) { Nation* nationPtr = nation_array[nationRecno]; nationPtr->add_expense( EXPENSE_FIRM, (float)firm_res[firmId]->setup_cost); // setup cost of the firm } return firmRecno; } //---------- End of function FirmArray::build_firm ---------// //--------- Begin of function FirmArray::create_firm ---------// // // create_firm() will be called directly by : // // 1. FirmArray::build_firm() for setting up a new firm // 2. FirmArray::read_file() when loading game. // // firmId = firm type id // // Return : the record no. of the newly added firm // int FirmArray::create_firm(int firmId) { Firm* firmPtr; switch(firmId) { case FIRM_BASE: firmPtr = new FirmBase; break; case FIRM_CAMP: firmPtr = new FirmCamp; break; case FIRM_FACTORY: firmPtr = new FirmFactory; break; case FIRM_INN: firmPtr = new FirmInn; break; case FIRM_MARKET: firmPtr = new FirmMarket; break; case FIRM_MINE: firmPtr = new FirmMine; break; case FIRM_RESEARCH: firmPtr = new FirmResearch; break; case FIRM_WAR_FACTORY: firmPtr = new FirmWar; break; case FIRM_HARBOR: firmPtr = new FirmHarbor; break; case FIRM_MONSTER: firmPtr = new FirmMonster; break; default: err_now("FirmArray::create_firm()"); } //----------------------------------------// linkin(&firmPtr); firmPtr->firm_recno = recno(); return firmPtr->firm_recno; } //----------- End of function FirmArray::create_firm ---------// //--------- Begin of function FirmArray::firm_class_size ---------// // // Return the size of the specified class. // This function will be called by FirmArray::write_file() // // id = the id of the job // int FirmArray::firm_class_size(int id) { switch(id) { case FIRM_BASE: return sizeof(FirmBase); case FIRM_CAMP: return sizeof(FirmCamp); case FIRM_FACTORY: return sizeof(FirmFactory); case FIRM_INN: return sizeof(FirmInn); case FIRM_MARKET: return sizeof(FirmMarket); case FIRM_MINE: return sizeof(FirmMine); case FIRM_RESEARCH: return sizeof(FirmResearch); case FIRM_WAR_FACTORY: return sizeof(FirmWar); case FIRM_HARBOR: return sizeof(FirmHarbor); case FIRM_MONSTER: return sizeof(FirmMonster); default: err_now( "FirmArray::firm_class_size" ); } return 0; } //----------- End of function FirmArray::firm_class_size ---------// //--------- Begin of function FirmArray::del_firm ---------// // // Warning : After calling this function, the recno() is still // pointing to the deleted record. // So go() to a new record to prevent running NULL object // // recNo = the no. of the record to be deleted // (default : current record no.) // void FirmArray::del_firm(int recNo) { Firm* firmPtr = firm_array[recNo]; int xLoc = firmPtr->center_x; int yLoc = firmPtr->center_y; firmPtr->deinit(); // we must call deinit() first delete firmPtr; linkout(recNo); } //----------- End of function FirmArray::del_firm ---------// //--------- Begin of function FirmArray::process ---------// // // Process all firm in firm_array for action and movement for next frame // // Return : 1 - all firm in the FirmArray has been processed // 0 - only some has been processed, not all // int FirmArray::process() { int i; Firm *firmPtr; //----- each time process some firm only ------// for( i=1 ; i<=size() ; i++ ) { firmPtr = (Firm*) get_ptr(i); if( !firmPtr ) // the firm has been deleted continue; err_when(firmPtr->firm_recno!=i); //-------- system yield ---------// if( i%20==1 ) sys.yield(); #if defined(DEBUG) && defined(ENABLE_LOG) String logStr; logStr = "begin process firm "; logStr += firmPtr->firm_recno; logStr += " nation="; logStr += firmPtr->nation_recno; LOG_MSG(logStr); #endif if(i==50) { FirmMarket *mPtr = (FirmMarket*) firmPtr; MarketGoods *marketGoods = mPtr->market_goods_array; marketGoods++; if(marketGoods->stock_qty) int debug = 0; } //-------- process visibility -----------// if( firmPtr->nation_recno == nation_array.player_recno || ( firmPtr->nation_recno && nation_array[firmPtr->nation_recno]->is_allied_with_player ) ) { world.visit( firmPtr->loc_x1, firmPtr->loc_y1, firmPtr->loc_x2, firmPtr->loc_y2, EXPLORE_RANGE-1 ); } //--------- process and process_ai firms ----------// if( firmPtr->under_construction ) { LOG_MSG(" process_construction"); firmPtr->process_construction(); LOG_MSG(m.get_random_seed() ); } else { if( i%FRAMES_PER_DAY == int(sys.frame_count%FRAMES_PER_DAY) ) // only process each firm once per day { //### begin alex 22/9 ###// #ifdef DEBUG unsigned long profileStartTime = m.get_time(); #endif //#### end alex 22/9 ####// LOG_MSG(" next_day"); firmPtr->next_day(); LOG_MSG(m.get_random_seed() ); //### begin alex 22/9 ###// #ifdef DEBUG firm_profile_time += m.get_time() - profileStartTime; #endif //#### end alex 22/9 ####// //-- if the hit points drop to zero, the firm should be deleted --// if( firmPtr->hit_points <=0 ) { se_res.sound( firmPtr->center_x, firmPtr->center_y, 1, 'F', firmPtr->firm_id, "DEST" ); del_firm( firmPtr->firm_recno ); continue; } //--------- process AI ------------// #ifdef DEBUG if(config.disable_ai_flag==0 && firmPtr->firm_ai) #else if( firmPtr->firm_ai ) #endif { LOG_MSG(" process_common_ai"); firmPtr->process_common_ai(); LOG_MSG(m.get_random_seed() ); //### begin alex 22/9 ###// #ifdef DEBUG unsigned long profileAiStartTime = m.get_time(); #endif //#### end alex 22/9 ####// LOG_MSG(" process_ai"); firmPtr->process_ai(); LOG_MSG(m.get_random_seed()); //### begin alex 22/9 ###// #ifdef DEBUG firm_ai_profile_time += m.get_time() - profileAiStartTime; #endif //#### end alex 22/9 ####// if( is_deleted(i) ) // the firm may have been deleted in process_ai() continue; } //--- think about having other nations capturing this firm ----// if( info.game_date%60==i%60 ) // this is not limited to ai firms only, it is called on all firms as AI can capture other player's firm firmPtr->think_capture(); } } //-------- process animation ---------// LOG_MSG(" process_animation"); firmPtr->process_animation(); LOG_MSG( m.get_random_seed() ); } return 0; } //----------- End of function FirmArray::process ---------// //--------- Begin of function FirmArray::next_month ---------// // void FirmArray::next_month() { int i; Firm* firmPtr; LOG_MSG("begin FirmArray::next_month"); LOG_MSG(m.get_random_seed() ); for(i=1; i <=size() ; i++) { firmPtr = (Firm*)get_ptr(i); if( firmPtr && !firmPtr->under_construction ) { LOG_MSG("Firm next_month"); LOG_MSG( i ); firmPtr->next_month(); LOG_MSG(m.get_random_seed() ); } } LOG_MSG("end FirmArray::next_month"); LOG_MSG(m.get_random_seed() ); } //----------- End of function FirmArray::next_month -----------// //--------- Begin of function FirmArray::next_year ---------// // void FirmArray::next_year() { int i; Firm* firmPtr; LOG_MSG("begin FirmArray::next_year"); LOG_MSG(m.get_random_seed() ); for(i=1; i <=size() ; i++) { firmPtr = (Firm*)get_ptr(i); if( firmPtr && !firmPtr->under_construction ) { LOG_MSG("Firm next_month"); LOG_MSG( i ); firmPtr->next_year(); LOG_MSG(m.get_random_seed() ); } } LOG_MSG("end FirmArray::next_year"); LOG_MSG(m.get_random_seed() ); } //----------- End of function FirmArray::next_year -----------// //--------- Begin of function FirmArray::draw_dot ---------// // // Draw tiny dots on map window representing the location of the firm // void FirmArray::draw_dot() { char* vgaBufPtr = vga_back.buf_ptr(); char* writePtr; int i, x, y; Firm* firmPtr; FirmBuild* firmBuild; char* nationColorArray = nation_array.nation_color_array; char nationColor; int vgaBufPitch = vga_back.buf_pitch(); const unsigned int excitedColorCount = 4; char excitedColorArray[MAX_NATION+1][excitedColorCount]; for( i = 0; i <= MAX_NATION; ++i ) { if( i == 0 || !nation_array.is_deleted(i) ) { char *remapTable = game.get_color_remap_table(i, 0); excitedColorArray[i][0] = remapTable[0xe0]; excitedColorArray[i][1] = remapTable[0xe1]; excitedColorArray[i][2] = remapTable[0xe2]; excitedColorArray[i][3] = remapTable[0xe3]; } else { excitedColorArray[i][0] = excitedColorArray[i][1] = excitedColorArray[i][2] = excitedColorArray[i][3] = (char) V_WHITE; } } for(i=1; i <=size() ; i++) { firmPtr = (Firm*)get_ptr(i); if( !firmPtr ) continue; firmBuild = firm_res.get_build(firmPtr->firm_build_id); writePtr = vgaBufPtr + (MAP_Y1+firmPtr->loc_y1)*vgaBufPitch + (MAP_X1+firmPtr->loc_x1); nationColor = info.game_date - firmPtr->last_attacked_date > 2 ? nationColorArray[firmPtr->nation_recno] : excitedColorArray[firmPtr->nation_recno][sys.frame_count % excitedColorCount]; char shadowColor = (char) VGA_GRAY; // ###### begin Gilbert 17/10 #######// int firmWidth = firmBuild->loc_width; int firmHeight = firmBuild->loc_height; if( firmPtr->nation_recno == 0 && firmWidth == STD_TOWN_LOC_WIDTH && firmHeight == STD_TOWN_LOC_HEIGHT) { --firmWidth; // all monster are all 4x4, may mixed with independent town on mini-map --firmHeight; } for( y=firmHeight ; y>0 ; y--, writePtr+=vgaBufPitch-firmWidth ) { for( x=firmWidth ; x>0 ; x--, writePtr++ ) { if( *writePtr != UNEXPLORED_COLOR ) *writePtr = nationColor; } if( *(writePtr+vgaBufPitch) != UNEXPLORED_COLOR) *(writePtr+vgaBufPitch) = shadowColor; } for( x = firmWidth; x>0; x--) { if( *(++writePtr) != UNEXPLORED_COLOR ) *writePtr = shadowColor; } // ###### end Gilbert 17/10 #######// } } //----------- End of function FirmArray::draw_dot -----------// //### begin alex 22/9 ###// //--------- Begin of function FirmArray::draw_profile ---------// void FirmArray::draw_profile() { #ifdef DEBUG static unsigned long lastDrawTime = m.get_time(); if(m.get_time() >= lastDrawTime + 1000) { last_firm_profile_time = firm_profile_time; lastDrawTime = m.get_time(); firm_profile_time = 0L; } String str; str = "Firm : "; font_news.disp( ZOOM_X1+10, ZOOM_Y1+60, str, MAP_X2); str = ""; str += last_firm_ai_profile_time; font_news.disp( ZOOM_X1+60, ZOOM_Y1+60, str, MAP_X2); str = ""; str += last_firm_profile_time; font_news.disp( ZOOM_X1+100, ZOOM_Y1+60, str, MAP_X2); #endif } //----------- End of function FirmArray::draw_profile -----------// //#### end alex 22/9 ####// /* //--------- Begin of function FirmArray::skip ---------// // // Skip to prev/next firms within the firm filter. // // skipDirection = -1 - backward one record // 1 - forward one record // void FirmArray::skip(int skipDirection) { int firmRecno=recno(); Firm *firmPtr; while(1) { firmRecno += ( skipDirection>0 ? 1 : -1 ); //------- loop to front/back --------// if( firmRecno > size() ) firmRecno = firmRecno - size(); if( firmRecno < 1 ) firmRecno = firmRecno + size(); //----- if no firm under current firm filter ----// if( firmRecno == recno() ) // after one loop, there is still no match return; //--------- if it is deleted --------// if( is_deleted(firmRecno) ) continue; //------ if it is not in firm filter -------// if( !firm_array[firmRecno]->draw_map_loc(2) ) //only draw when the firm is in filter continue; //--------- go to the firm ----------// world.go_firm(firmRecno); return; } } //---------- End of function FirmArray::skip ----------// */ #ifdef DEBUG //------- Begin of function FirmArray::operator() -----// Firm* FirmArray::operator()() { Firm* firmPtr = (Firm*) get_ptr(); // if recno()==0, get_ptr() returns NULL err_if( !firmPtr ) err_now( "FirmArray[recno()] is deleted" ); return firmPtr; } //--------- End of function FirmArray::operator() ----// //------- Begin of function FirmArray::operator[] -----// Firm* FirmArray::operator[](int recNo) { Firm* firmPtr = (Firm*) get_ptr(recNo); if( !firmPtr ) err.run( "FirmArray[] is deleted" ); return firmPtr; } //--------- End of function FirmArray::operator[] ----// #endif