123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : ONATION.CPP
- //Description : Object Nation - part 1
- #include <OSTR.h>
- #include <OSYS.h>
- #include <ODATE.h>
- #include <OBOX.h>
- #include <OVGA.h>
- #include <OFONT.h>
- #include <ONEWS.h>
- #include <OWORLD.h>
- #include <OFIRM.h>
- #include <OGAME.h>
- #include <OPOWER.h>
- #include <OREGIONS.h>
- #include <ORACERES.h>
- #include <OTALKRES.h>
- #include <OMONSRES.h>
- #include <OGODRES.h>
- #include <OTOWN.h>
- #include <OSPY.h>
- #include <OF_MARK.h>
- #include <OF_BASE.h>
- #include <OF_MONS.h>
- #include <OTECHRES.h>
- #include <ONATION.h>
- #include <OREBEL.h>
- #include <OREMOTE.h>
- //-------- Define static variables --------//
- char* NationRelation::relation_status_str_array[5] =
- {
- "War", "Tense", "Neutral", "Friendly", "Alliance"
- };
- //--------- Define static functions -------//
- static int succeed_king_loyalty_change(int thisRaceId, int newKingRaceId, int oldKingRaceId);
- //--------- Begin of function NationBase::Nation --------//
- NationBase::NationBase()
- {
- memset( this, 0, sizeof(NationBase) );
- }
- //---------- End of function NationBase::Nation --------//
- //--------- Begin of function NationBase::~Nation --------//
- NationBase::~NationBase()
- {
- #ifdef DEBUG
- err_when( nation_recno ); // deinit() must be called first before this destructor is called
- for( int i=0 ; i<MAX_RACE ; i++ )
- err_when( base_count_array[i] > 0 ); // it should be all zeros
- #endif
- }
- //---------- End of function NationBase::~Nation --------//
- //--------- Begin of function NationBase::init --------//
- //
- // This function will be called directly by
- //
- // <int> nationType = the nation type (NATION_???)
- // <int> raceId = id. of the race
- // <int> colorSchemeId = color scheme id. of the nation
- // [DWORD] playerId = an unique player id. (for multiplayer game)
- //
- void NationBase::init(int nationType, int raceId, int colorSchemeId, DWORD playerId)
- {
- //------------- set vars ---------------//
- nation_type = nationType;
- race_id = raceId;
- color_scheme_id = colorSchemeId;
- player_id = playerId;
- colorSchemeId = min( colorSchemeId, MAX_COLOR_SCHEME );
- nation_color = game.color_remap_array[colorSchemeId].main_color;
- last_war_date = info.game_date;
- //------- if this is the local player's nation -------//
- if( nation_type==NATION_OWN )
- nation_array.player_recno = nation_recno;
- //---------- init game vars ------------//
- static int start_up_cash_array[] = { 4000, 7000, 12000, 20000 };
- if( is_ai() )
- cash = (float) start_up_cash_array[config.ai_start_up_cash-1];
- else
- cash = (float) start_up_cash_array[config.start_up_cash-1];
- food = (float) 5000; // startup food is 5000 for all nations in all settings
- //---- initialize this nation's relation on other nations ----//
- for( int i=nation_array.size() ; i>0 ; i-- )
- {
- if( nation_array.is_deleted(i) )
- continue;
- init_relation(i);
- nation_array[i]->init_relation(nation_recno);
- }
- //--------- init technology ----------//
- tech_res.init_nation_tech(nation_recno);
- //------- reset all god knowledge --------//
- god_res.init_nation_know(nation_recno);
- //### begin alex 23/9 ###//
- if(remote.is_enable() && nation_recno && !is_ai() && m.is_file_exist("TECHGOD.SYS"))
- {
- tech_res.inc_all_tech_level(nation_recno);
- tech_res.inc_all_tech_level(nation_recno);
- tech_res.inc_all_tech_level(nation_recno);
- god_res.enable_know_all(nation_recno);
- }
- //#### end alex 23/9 ####//
- }
- //----------- End of function NationBase::init ---------//
- //--------- Begin of function NationBase::deinit --------//
- //
- // When a nation is to be deleted, NationBase::deinit() must
- // be called first from nation_array before calling its
- // destructor as when it deinitalizes units, some functions
- // will need to access the nation_array[].
- //
- void NationBase::deinit()
- {
- if( nation_recno==0 ) // has been deinitialized
- return;
- //---- delete all talk messages to/from this nation ----//
- talk_res.del_all_nation_msg(nation_recno);
- //------- close down all firms --------//
- close_all_firm();
- //---- neutralize all towns belong to this nation ----//
- Town* townPtr;
- int i;
- for( i=town_array.size() ; i>0 ; i-- )
- {
- if( town_array.is_deleted(i) )
- continue;
- townPtr = town_array[i];
- if( townPtr->nation_recno == nation_recno )
- townPtr->set_nation(0);
- }
- //------------- deinit our spies -------------//
- for( i=spy_array.size() ; i>0 ; i-- )
- {
- if( spy_array.is_deleted(i) )
- continue;
- Spy* spyPtr = spy_array[i];
- //-----------------------------------------------------//
- // Convert all of spies of this nation to normal units,
- // so there will be no more spies of this nation.
- //-----------------------------------------------------//
- if( spyPtr->true_nation_recno == nation_recno ) // drop spy identities of spies in towns, firms and mobile ones
- spyPtr->drop_spy_identity();
- //-----------------------------------------------------//
- // For spies of other nation cloaked as this nation,
- // their will uncover their cloak and change back
- // to their original nation.
- //-----------------------------------------------------//
- else if( spyPtr->cloaked_nation_recno == nation_recno )
- spyPtr->change_cloaked_nation(spyPtr->true_nation_recno);
- err_when( spyPtr->true_nation_recno == nation_recno || // there should be no more spies associated with this nation
- spyPtr->cloaked_nation_recno == nation_recno );
- }
- //----- deinit all units belonging to this nation -----//
- deinit_all_unit();
- //-------- if the viewing nation is this nation -------//
- if( !sys.signal_exit_flag )
- {
- if( info.default_viewing_nation_recno == nation_recno )
- {
- info.default_viewing_nation_recno = nation_array.player_recno;
- sys.set_view_mode(MODE_NORMAL);
- }
- else if( info.viewing_nation_recno == nation_recno )
- sys.set_view_mode(MODE_NORMAL); // it will set viewing_nation_recno to default_viewing_nation_recno
- // ##### begin Gilbert 22/10 #######//
- // if deleting own nation, darken view mode buttons
- if( nation_recno == nation_array.player_recno )
- {
- sys.disp_view_mode(1);
- }
- // ##### end Gilbert 22/10 #######//
- }
- nation_recno = 0;
- }
- //----------- End of function NationBase::deinit ---------//
- //--------- Begin of function NationBase::init_relation --------//
- //
- // Initialize the relation vars with the given nation.
- //
- // <int> relationNationRecno - recno of the NationRelation to set.
- //
- void NationBase::init_relation(int relationNationRecno)
- {
- NationRelation* nationRelation = relation_array+relationNationRecno-1;
- memset( nationRelation, 0, sizeof(NationRelation) );
- set_relation_should_attack(relationNationRecno, relationNationRecno!=nation_recno, COMMAND_AUTO);
- if( is_ai() && nation_array[relationNationRecno]->is_ai() ) // AI has contact with each other in the beginning of the game.
- nationRelation->has_contact = 1;
- else
- nationRelation->has_contact = relationNationRecno==nation_recno || config.explore_whole_map; // if the map is blackened out, no contact in the beginning
- nationRelation->trade_treaty = relationNationRecno==nation_recno;
- nationRelation->status = NATION_NEUTRAL;
- nationRelation->ai_relation_level = NATION_NEUTRAL * RELATION_LEVEL_PER_STATUS;
- nationRelation->last_change_status_date = info.game_date;
- if( relationNationRecno == nation_recno ) // own nation
- relation_status_array[relationNationRecno-1] = NATION_ALLIANCE; // for facilitating searching
- else
- relation_status_array[relationNationRecno-1] = NATION_NEUTRAL;
- set_relation_passable(relationNationRecno, NATION_FRIENDLY);
- is_allied_with_player = 0;
- }
- //----------- End of function NationBase::init_relation ---------//
- //--------- Begin of function NationBase::close_all_firm --------//
- //
- // Close down all firms under this nation.
- //
- void NationBase::close_all_firm()
- {
- int i;
- for( i=firm_array.size() ; i>0 ; i-- )
- {
- if( !firm_array.is_deleted(i) &&
- firm_array[i]->nation_recno == nation_recno )
- {
- firm_array.del_firm(i);
- }
- }
- }
- //----------- End of function NationBase::close_all_firm ---------//
- //--------- Begin of function NationBase::deinit_all_unit --------//
- //
- // Deinit all units belonging to this nation when this nation is deinitialized.
- //
- void NationBase::deinit_all_unit()
- {
- //--- update total_human_unit so the numbers will be correct ---//
- #ifndef DEBUG // only do this in release version to on-fly fix bug
- nation_array.update_statistic();
- #endif
- //--------------------------------------//
- int i;
- Unit* unitPtr;
- for( i=unit_array.size() ; i>0 ; i-- )
- {
- if( unit_array.is_deleted(i) )
- {
- unitPtr = (Unit*) unit_array.get_ptr(i); // this unit is dying, so is_deleted() return 1;
-
- if( !unitPtr )
- continue;
- if( unitPtr->nation_recno == nation_recno )
- unit_array.del(i);
- continue;
- }
- //--------------------------------------------//
- unitPtr = unit_array[i];
- if( unitPtr->nation_recno != nation_recno )
- continue;
- //----- only human units will betray -----//
- if( unitPtr->race_id )
- {
- unitPtr->loyalty = 0; // force it to detray
- if( unitPtr->think_betray() )
- continue;
- }
- //--- if the unit has not changed nation, the unit will disappear ---//
- if( unit_array.get_ptr(i) )
- unit_array.del(i);
- }
- //------------ debug code -------------//
- for( i=unit_array.size() ; i>0 ; i-- )
- {
- if( unit_array.is_deleted(i) )
- continue;
- unitPtr = unit_array[i];
-
- err_when( unitPtr->nation_recno == nation_recno ); // they should have been all deleted.
- }
- }
- //----------- End of function NationBase::deinit_all_unit ---------//
- //--------- Begin of function NationBase::hand_over_to --------//
- //
- // <int> handoverNationRecno - hand over the entire nation to this nation.
- //
- void NationBase::hand_over_to(int handoverNationRecno)
- {
- rebel_array.stop_attack_nation(nation_recno);
- town_array.stop_attack_nation(nation_recno);
- unit_array.stop_all_war(nation_recno);
- monster_res.stop_attack_nation(nation_recno);
- nation_hand_over_flag = nation_recno;
- //--- hand over units (should hand over units first as you cannot change a firm's nation without changing the nation of the overseer there ---//
- Unit* unitPtr;
- int i;
- for( i=unit_array.size() ; i>0 ; i-- )
- {
- if( unit_array.is_deleted(i) )
- {
- //-- If the unit is dying and isn't truly deleted yet, delete it now --//
- if( !unit_array.is_truly_deleted(i) &&
- unit_array[i]->nation_recno == nation_recno )
- {
- unit_array.die(i);
- }
- continue;
- }
- //---------------------------------------//
- unitPtr = unit_array[i];
- if( unitPtr->nation_recno != nation_recno )
- continue;
- //----- if it is a god, resign it -------//
- if( god_res.is_god_unit(unitPtr->unit_id) )
- {
- unitPtr->resign(COMMAND_AUTO);
- continue;
- }
- //----- if it is a spy cloaked as this nation -------//
- //
- // If the unit is a overseer of a Camp or Base,
- // the Camp or Base will change nation as a result.
- //
- //---------------------------------------------------//
- if( unitPtr->spy_recno )
- unitPtr->spy_change_nation(handoverNationRecno, COMMAND_AUTO);
- else
- unitPtr->change_nation(handoverNationRecno);
- }
- //------- hand over firms ---------//
- for( i=firm_array.size() ; i>0 ; i-- )
- {
- if( !firm_array.is_deleted(i) &&
- firm_array[i]->nation_recno == nation_recno )
- {
- firm_array[i]->change_nation(handoverNationRecno);
- }
- }
- //------- hand over towns ---------//
- for( i=town_array.size() ; i>0 ; i-- )
- {
- if( !town_array.is_deleted(i) &&
- town_array[i]->nation_recno == nation_recno )
- {
- town_array[i]->set_nation(handoverNationRecno);
- }
- }
- //-------------------------------------------------//
- //
- // For the spies of this nation cloaked into other nations,
- // we need to update their true_nation_recno.
- //
- //-------------------------------------------------//
- Spy* spyPtr;
- for( i=spy_array.size() ; i>0 ; i-- )
- {
- if( spy_array.is_deleted(i) )
- continue;
- spyPtr = spy_array[i];
- err_when( spyPtr->cloaked_nation_recno == nation_recno ); // there should be no units in this nation after the above deinitialization
- if( spyPtr->true_nation_recno == nation_recno )
- spyPtr->change_true_nation(handoverNationRecno);
- }
- //------- delete this nation from nation_array -------//
- nation_array.del_nation(nation_recno);
- nation_hand_over_flag = 0;
- }
- //----------- End of function NationBase::hand_over_to ---------//
- //--------- Begin of function NationBase::set_king --------//
- //
- // Set the king unit recno.
- //
- // <int> kingUnitRecno - unit recno of the king
- // <int> firstKing - whether this is the first king of the nation.
- //
- void NationBase::set_king(int kingUnitRecno, int firstKing)
- {
- king_unit_recno = kingUnitRecno;
- Unit* kingUnit = unit_array[king_unit_recno];
- //--- if this unit currently has not have leadership ---//
- if( kingUnit->skill.skill_id != SKILL_LEADING )
- {
- kingUnit->skill.skill_id = SKILL_LEADING;
- kingUnit->skill.skill_level = 0;
- }
- kingUnit->set_rank(RANK_KING);
- kingUnit->stop2(); // clear the existing order, as there might be an assigning to firm/town order. But kings cannot be assigned to towns or firms as workers.
- //---------- king related vars ----------//
- if( nation_type == NATION_AI || !firstKing ) // for succession, no longer use the original player name
- nation_name_id = kingUnit->name_id;
- else
- nation_name_id = -nation_recno; // for human players, the name is retrieved from NationArray::human_name_array
- race_id = kingUnit->race_id;
- king_leadership = kingUnit->skill.skill_level;
- err_when( !nation_name_id );
- err_when( !race_id );
- }
- //----------- End of function NationBase::set_king ---------//
- //--------- Begin of function NationBase::nation_name --------//
- //
- char* NationBase::nation_name()
- {
- #if(defined(SPANISH))
- strncpy( nation_name_str, "Reino de ", NATION_NAME_LEN );
- nation_name_str[NATION_NAME_LEN]=NULL;
- strncat( nation_name_str, king_name(1), NATION_NAME_LEN ); // 1-get the first word of the name only
- nation_name_str[NATION_NAME_LEN]=NULL;
- #elif(defined(FRENCH))
- strncpy( nation_name_str, "Royaume de ", NATION_NAME_LEN );
- nation_name_str[NATION_NAME_LEN]=NULL;
- strncat( nation_name_str, king_name(1), NATION_NAME_LEN ); // 1-get the first word of the name only
- nation_name_str[NATION_NAME_LEN]=NULL;
- #else
- // German and US
- strncpy( nation_name_str, king_name(1), NATION_NAME_LEN ); // 1-get the first word of the name only
- nation_name_str[NATION_NAME_LEN]=NULL;
- strncat( nation_name_str, "'s ", NATION_NAME_LEN ); // 1-get the first word of the name only
- nation_name_str[NATION_NAME_LEN]=NULL;
- strncat( nation_name_str, translate.process("Kingdom"), NATION_NAME_LEN );
- nation_name_str[NATION_NAME_LEN]=NULL;
- #endif
- return nation_name_str; // each name needs to have its own var as multiple nation names will be displayed at the same time in diplomatic talk choices
- }
- //----------- End of function NationBase::nation_name ---------//
- //--------- Begin of function NationBase::king_name --------//
- //
- // [int] firstWordOnly - whether only get the first word of the name.
- // (default: 0)
- //
- char* NationBase::king_name(int firstWordOnly)
- {
- if( nation_name_id < 0 ) // human player custom names
- {
- return nation_array.get_human_name(nation_name_id, firstWordOnly);
- }
- else
- {
- if( firstWordOnly )
- return race_res[race_id]->get_single_name( (WORD) nation_name_id );
- else
- return race_res[race_id]->get_name( (WORD) nation_name_id );
- }
- }
- //----------- End of function NationBase::king_name ---------//
- //------- Begin of function NationBase::cash_str ------//
- //
- // Return a text string with the current nation treasure and profit
- // in the past 30 days.
- //
- char* NationBase::cash_str()
- {
- static String str;
- if( cash >= 0 )
- {
- str = m.format( (int)cash, 4 ); // format type 4 - no thousand separators
- }
- else
- {
- str = "-";
- str += m.format( (int)-cash, 4 ); // format type 4 - no thousand separators
- }
- //--------------------------------------//
- int curProfit = (int) profit_365days();
- if( curProfit )
- {
- str += " (";
- if( curProfit > 0 )
- str += "+";
- else
- str += "-";
- str += m.format( abs(curProfit), 4 ); // format type 4 - no thousand separators
- str += ")";
- }
- return str;
- }
- //------- End of function NationBase::cash_str -------//
- //------- Begin of function NationBase::food_str ------//
- //
- // Return a text string with the current nation treasure and profit
- // in the past 30 days.
- //
- char* NationBase::food_str()
- {
- static String str;
- if( food >= 0 )
- {
- str = m.format( (int)food, 4 ); // format type 4 - no thousand separators
- }
- else
- {
- str = "-";
- str += m.format( (int)-food, 4 ); // format type 4 - no thousand separators
- }
- //--------------------------------------//
- int foodChange = (int) food_change_365days();
- if( foodChange )
- {
- str += " (";
- if( foodChange > 0 )
- str += "+";
- else
- str += "-";
- str += m.format( abs(foodChange), 4 ); // format type 4 - no thousand separators
- str += ")";
- }
- return str;
- }
- //------- End of function NationBase::food_str -------//
- //---------- Begin of function NationBase::next_day --------//
- //
- // This function is called every day.
- //
- void NationBase::next_day()
- {
- //------ post is at war flag -------/
- if( is_at_war_today )
- last_war_date = info.game_date;
- is_at_war_yesterday = is_at_war_today;
- is_at_war_today = 0;
- //--- if the king is dead, and now looking for a successor ---//
- if( !king_unit_recno )
- {
- if( info.game_date%3 == nation_recno%3 ) // decrease 1 loyalty point every 3 days
- change_all_people_loyalty(-1);
- }
- //---------- debug code ------------//
- #ifdef DEBUG
- //---------- check king -----------//
-
- if( king_unit_recno )
- {
- Unit* unitPtr = unit_array[king_unit_recno];
- err_when( unitPtr->rank_id != RANK_KING );
- err_when( unitPtr->nation_recno != nation_recno );
- }
- //---------- check relation -----------//
- err_when( get_relation_status(nation_recno) != NATION_ALLIANCE ); // relation to own nation must be alliance
-
- #endif
- //------ check if this nation has won the game -----//
- check_win();
- //-- if the player still hasn't selected a unit to succeed the died king, declare defeated if the all units are killed --//
- if( !king_unit_recno )
- check_lose();
- //---------- debug code --------------//
- /*
- #ifdef DEBUG
- int totalHumanCount=0;
- for( int i=unit_array.size() ; i>0 ; i-- )
- {
- Unit* unitPtr = (Unit*) unit_array.get_ptr(i);
- if( unitPtr &&
- unitPtr->nation_recno == nation_recno &&
- unitPtr->race_id &&
- unitPtr->rank_id != RANK_KING )
- {
- totalHumanCount++;
- }
- }
- for( i=firm_array.size() ; i>0 ; i-- )
- {
- if( firm_array.is_deleted(i) )
- continue;
- Firm* firmPtr = firm_array[i];
- if( firmPtr->nation_recno != nation_recno )
- continue;
- if( firmPtr->firm_id == FIRM_CAMP ||
- firmPtr->firm_id == FIRM_BASE )
- {
- totalHumanCount += firmPtr->worker_count;
- }
- }
- err_when( total_human_count != totalHumanCount );
- #endif
- */
- }
- //----------- End of function NationBase::next_day ---------//
- //---------- Begin of function NationBase::next_month --------//
- //
- // This function is called every month.
- //
- void NationBase::next_month()
- {
- //--------------------------------------------------//
- // When the two nations, whose relationship is Tense,
- // do not have new conflicts for 3 years, their
- // relationship automatically becomes Neutral.
- //--------------------------------------------------//
- NationRelation* nationRelation;
- for( int i=1 ; i<=nation_array.size() ; i++ )
- {
- if( nation_array.is_deleted(i) )
- continue;
- nationRelation = get_relation(i);
- if( nationRelation->status == NATION_TENSE &&
- info.game_date >= nationRelation->last_change_status_date + 365*3 )
- {
- set_relation_status(i, NATION_NEUTRAL);
- }
- //--- update good_relation_duration_rating ---//
- else if( nationRelation->status == NATION_FRIENDLY )
- nationRelation->good_relation_duration_rating += (float) 0.2; // this is the monthly increase
- else if( nationRelation->status == NATION_ALLIANCE )
- nationRelation->good_relation_duration_rating += (float) 0.4;
- }
- //----- increase reputation gradually -----//
- if( reputation < 100 )
- change_reputation((float)0.5);
- }
- //---------- End of function NationBase::next_month --------//
- //---------- Begin of function NationBase::next_year --------//
- //
- // This function is called every year
- //
- void NationBase::next_year()
- {
- //------ post financial data --------//
- last_year_income = cur_year_income;
- cur_year_income = (float) 0;
- last_year_expense = cur_year_expense;
- cur_year_expense = (float) 0;
- last_year_fixed_income = cur_year_fixed_income;
- cur_year_fixed_income = (float) 0;
- last_year_fixed_expense = cur_year_fixed_expense;
- cur_year_fixed_expense = (float) 0;
- last_year_profit = cur_year_profit;
- cur_year_profit = (float) 0;
- last_year_cheat = cur_year_cheat;
- cur_year_cheat = (float) 0;
- //------ post income & expense breakdown ------//
- int i;
- for( i=0 ; i<INCOME_TYPE_COUNT ; i++ )
- {
- last_year_income_array[i] = cur_year_income_array[i];
- cur_year_income_array[i] = (float) 0;
- }
- for( i=0 ; i<EXPENSE_TYPE_COUNT ; i++ )
- {
- last_year_expense_array[i] = cur_year_expense_array[i];
- cur_year_expense_array[i] = (float) 0;
- }
- //------ post good change data ------//
- last_year_food_in = cur_year_food_in;
- cur_year_food_in = (float) 0;
- last_year_food_out = cur_year_food_out;
- cur_year_food_out = (float) 0;
- last_year_food_change = cur_year_food_change;
- cur_year_food_change = (float) 0;
- //---------- post imports ----------//
- NationRelation* nationRelation = relation_array;
- for( i=0; i<MAX_NATION ; i++, nationRelation++ )
- {
- for( int j=0 ; j<IMPORT_TYPE_COUNT ; j++ )
- {
- nationRelation->last_year_import[j] = nationRelation->cur_year_import[j];
- nationRelation->cur_year_import[j] = (float) 0;
- }
- }
- //--------- post reputation ----------//
- last_year_reputation_change = cur_year_reputation_change;
- cur_year_reputation_change = (float) 0;
- }
- //---------- End of function NationBase::next_year --------//
- //---------- Begin of function NationBase::add_income --------//
- //
- // <int> incomeType - the income type
- // <float> incomeAmt - the amount of the income.
- // [int] fixedIncome - whether this is a fixed income, or
- // a variable income. (default: 0)
- //
- void NationBase::add_income(int incomeType, float incomeAmt, int fixedIncome)
- {
- err_when( incomeType < 0 || incomeType >= INCOME_TYPE_COUNT );
- cash += incomeAmt;
- cur_year_income_array[incomeType] += incomeAmt;
- cur_year_income += incomeAmt;
- cur_year_profit += incomeAmt;
- if( fixedIncome )
- cur_year_fixed_income += incomeAmt;
- }
- //---------- End of function NationBase::add_income --------//
- //---------- Begin of function NationBase::add_expense --------//
- //
- // <int> expenseType - the expense type
- // <float> incomeAmt - the amount of the income.
- // <int> fixedExpense - whether this is a fixed expense, or
- // a variable income. (default: 0)
- //
- void NationBase::add_expense(int expenseType, float expenseAmt, int fixedExpense)
- {
- err_when( expenseType < 0 || expenseType >= EXPENSE_TYPE_COUNT );
- cash -= expenseAmt;
- cur_year_expense_array[expenseType] += expenseAmt;
- cur_year_expense += expenseAmt;
- cur_year_profit -= expenseAmt;
- if( fixedExpense )
- cur_year_fixed_expense += expenseAmt;
- }
- //---------- End of function NationBase::add_expense --------//
- //---------- Begin of function NationBase::add_cheat --------//
- //
- // <float> cheatAmount - the cheating amount.
- //
- void NationBase::add_cheat(float cheatAmount)
- {
- if( sys.testing_session || nation_type == NATION_OWN )
- {
- add_income(INCOME_CHEAT, cheatAmount);
- }
- else // cheat less obviously, randomly add to one of the account at a random amount //
- {
- add_income( m.random(INCOME_TYPE_COUNT-1)+1, cheatAmount );
- cur_year_cheat += cheatAmount;
- }
- }
- //---------- End of function NationBase::add_cheat --------//
- //---------- Begin of function NationBase::import_goods --------//
- //
- // This function is called when the current nation imports
- // goods from a specific nation.
- //
- // <int> importType - type of goods imported.
- //
- // <int> importNationRecno - recno of the nation from which this
- // nation imports.
- //
- // <float> importAmt - the import amount
- //
- void NationBase::import_goods(int importType, int importNationRecno, float importAmt)
- {
- if( importNationRecno == nation_recno )
- return;
- NationRelation* nationRelation = get_relation(importNationRecno);
- nationRelation->cur_year_import[importType] += importAmt;
- nationRelation->cur_year_import[IMPORT_TOTAL] += importAmt;
- add_expense(EXPENSE_IMPORTS, importAmt, 1);
- nation_array[importNationRecno]->add_income(INCOME_EXPORTS, importAmt, 1);
- }
- //---------- End of function NationBase::import_goods --------//
- //---------- Begin of function NationBase::add_food --------//
- //
- // <float> foodToAdd - quantity of food to be added
- //
- void NationBase::add_food(float foodToAdd)
- {
- food += foodToAdd;
- cur_year_food_in += foodToAdd;
- cur_year_food_change += foodToAdd;
- }
- //----------- End of function NationBase::add_food ---------//
- //---------- Begin of function NationBase::consume_food --------//
- //
- // <float> foodConsumed - quantity of food consumed
- //
- void NationBase::consume_food(float foodConsumed)
- {
- food -= foodConsumed;
- cur_year_food_out += foodConsumed;
- cur_year_food_change -= foodConsumed;
- }
- //----------- End of function NationBase::consume_food ---------//
- //---------- Begin of function NationBase::change_reputation --------//
- //
- // <float> changeLevel - level of reputation to be changed.
- //
- void NationBase::change_reputation(float changeLevel)
- {
- //--- reputation increase more slowly when it is close to 100 ----//
- if( changeLevel > 0 && reputation > 0 )
- changeLevel = changeLevel * (150-reputation) / 150;
- //-----------------------------------------------//
- reputation += changeLevel;
- if( reputation > 100 )
- reputation = (float) 100;
- if( reputation < -100 )
- reputation = (float) -100;
- //------ update cur_year_reputation_change ------//
- cur_year_reputation_change += changeLevel;
- }
- //---------- End of function NationBase::change_reputation --------//
- //---------- Begin of function NationBase::change_ai_relation_level --------//
- //
- // Change this AI nation's subjectively relation levels towards the others,
- // the opposite nation's relation level is not the same as this.
- //
- // ai_relation_level is for AI only and will only be reviewed by AI functions.
- //
- // <short> nationRecno - the nation recno of the relation
- // <int> levelChange - the amount of change to the relation level
- //
- void NationBase::change_ai_relation_level(short nationRecno, int levelChange)
- {
- NationRelation* nationRelation = get_relation(nationRecno);
- int newLevel = nationRelation->ai_relation_level + levelChange;
- newLevel = min(newLevel, 100);
- newLevel = max(newLevel, 0 );
- nationRelation->ai_relation_level = newLevel;
- }
- //----------- End of function NationBase::change_ai_relation_level -----------//
- //---------- Begin of function NationBase::set_relation_status --------//
- //
- // <short> nationRecno - the nation recno of the relation
- // <char> newStatus - the new relationship status
- // [char] recursiveCall - whether this is a recursive call from itself
- // (default: 0)
- //
- void NationBase::set_relation_status(short nationRecno, char newStatus, char recursiveCall)
- {
- if( nationRecno == nation_recno ) // cannot set relation to itself
- return;
- NationRelation* nationRelation = get_relation(nationRecno);
- //--------- debug code --------// BUGHERE
- /*
- #ifdef DEBUG
- if( nation_array[nationRecno]->is_ai() && is_ai() ) // AI must terminate the treaty first before declaring war
- {
- err_when( nationRelation->status >= NATION_FRIENDLY &&
- newStatus == NATION_HOSTILE );
- }
- #endif
- */
- //-------------------------------------------------//
- //
- // When two nations agree to a cease-fire, there may
- // still be some bullets on their ways, and those
- // will set the status back to War status, so we need
- // the following code to handle this case.
- //
- //-------------------------------------------------//
- if( !recursiveCall &&
- nationRelation->status == NATION_TENSE &&
- newStatus == NATION_HOSTILE &&
- info.game_date < nationRelation->last_change_status_date + 5 ) // 5 days after the cease-fire, the nation will remain cease-fire
- {
- return;
- }
- //-------------------------------------------------//
- //
- // If the nation cease fire or form a friendly/alliance
- // treaty with a nation. And this nation current
- // has plan to attack that nation, then cancel the plan.
- //
- //-------------------------------------------------//
- if( is_ai() )
- {
- if( newStatus==NATION_TENSE || // cease fire
- newStatus>=NATION_FRIENDLY ) // new friendly/alliance treaty
- {
- if( ((Nation*)this)->ai_attack_target_nation_recno == nationRecno )
- ((Nation*)this)->reset_ai_attack_target();
- }
- }
- //------------------------------------------------//
- relation_status_array[nationRecno-1] = newStatus;
- nationRelation->status = newStatus;
- nationRelation->last_change_status_date = info.game_date;
- int newRelationLevel = newStatus * RELATION_LEVEL_PER_STATUS;
- if( newRelationLevel < nationRelation->ai_relation_level ) // only set it when the new value is lower than the current value
- nationRelation->ai_relation_level = newRelationLevel;
- set_relation_passable(nationRecno, NATION_FRIENDLY);
- //---------- set should_attack -------//
- if( newStatus==NATION_ALLIANCE || newStatus==NATION_FRIENDLY ||
- newStatus==NATION_TENSE )
- {
- set_relation_should_attack(nationRecno, 0, COMMAND_AUTO);
- }
- else if( newStatus==NATION_HOSTILE )
- {
- set_relation_should_attack(nationRecno, 1, COMMAND_AUTO);
- }
- //----- share the nation contact with each other -----//
- /*
- // these segment code will cause multiplayer sync problem
- if( newStatus == NATION_ALLIANCE )
- {
- Nation* withNation = nation_array[nationRecno];
- for( i=nation_array.size() ; i>0 ; i-- )
- {
- if( i==nation_recno || i==nationRecno )
- continue;
- if( nation_array.is_deleted(i) )
- continue;
- //-- if we have contact with this nation and our ally doesn't, share the contact with it --//
- if( get_relation(i)->has_contact &&
- withNation->get_relation(i)->has_contact==0 )
- {
- withNation->establish_contact(i);
- }
- }
- }
- */
- //--- if this is a call from a client function, not a recursive call ---//
- if( !recursiveCall )
- {
- nation_array[nationRecno]->set_relation_status(nation_recno, newStatus, 1);
- //-- auto terminate their trade treaty if two nations go into a war --//
- if( newStatus == NATION_HOSTILE )
- set_trade_treaty(nationRecno, 0);
- }
- }
- //----------- End of function NationBase::set_relation_status -----------//
- //---------- Begin of function NationBase::get_relation_status --------//
- char NationBase::get_relation_status(short nationRecno)
- {
- return relation_status_array[nationRecno-1];
- }
- //----------- End of function NationBase::get_relation_status -----------//
- //---------- Begin of function NationBase::set_relation_passable --------//
- void NationBase::set_relation_passable(short nationRecno, char status)
- {
- relation_passable_array[nationRecno-1] = (relation_status_array[nationRecno-1] >= status);
- }
- //----------- End of function NationBase::set_relation_passable -----------//
- //---------- Begin of function NationBase::get_relation_passable --------//
- char NationBase::get_relation_passable(short nationRecno)
- {
- return relation_passable_array[nationRecno-1];
- }
- //----------- End of function NationBase::get_relation_passable -----------//
- #ifdef DEBUG
- //---------- Begin of function NationBase::get_relation --------//
- //
- NationRelation* NationBase::get_relation(int nationRecno)
- {
- if( nationRecno<1 || nationRecno>MAX_NATION )
- err.run( "NationBase::get_relation()" );
- return relation_array+nationRecno-1;
- }
- //---------- End of function NationBase::get_relation --------//
- #endif
- //---------- Begin of function NationBase::set_relation_should_attack --------//
- void NationBase::set_relation_should_attack(short nationRecno, char newValue, char remoteAction)
- {
- if( !remoteAction && remote.is_enable() )
- {
- short *shortPtr = (short *) remote.new_send_queue_msg(MSG_NATION_SET_SHOULD_ATTACK, 3*sizeof(short));
- *shortPtr = nation_recno;
- shortPtr[1] = nationRecno;
- shortPtr[2] = newValue;
- }
- else
- {
- relation_should_attack_array[nationRecno-1] = newValue;
- get_relation(nationRecno)->should_attack = newValue;
- }
- }
- //---------- End of function NationBase::set_relation_should_attack --------//
- //---------- Begin of function NationBase::get_relation_should_attack --------//
- char NationBase::get_relation_should_attack(short nationRecno)
- {
- // ###### begin Gilbert 3/9 #######//
- // always can attack independent unit
- return nationRecno == 0 || relation_should_attack_array[nationRecno-1];
- // ###### end Gilbert 3/9 #######//
- }
- //---------- End of function NationBase::get_relation_should_attack --------//
- //------- Begin of function NationBase::form_friendly_treaty ------//
- //
- // <int> nationRecno - recno of the nation with which this nation
- // will form treaty.
- //
- void NationBase::form_friendly_treaty(int nationRecno)
- {
- err_when( nationRecno == nation_recno );
- err_when( nation_array.is_deleted(nationRecno) );
- set_relation_status(nationRecno, NATION_FRIENDLY);
- }
- //------- End of function NationBase::form_friendly_treaty -------//
- //------- Begin of function NationBase::form_alliance_treaty ------//
- //
- // <int> nationRecno - recno of the nation with which this nation
- // will form treaty.
- //
- void NationBase::form_alliance_treaty(int nationRecno)
- {
- err_when( nationRecno == nation_recno );
- err_when( nation_array.is_deleted(nationRecno) );
- set_relation_status(nationRecno, NATION_ALLIANCE);
- //--- allied nations are oblied to trade with each other ---//
- set_trade_treaty(nationRecno, 1);
- //------ set is_allied_with_player -------//
- if( nationRecno == nation_array.player_recno )
- is_allied_with_player = 1;
- if( nation_recno == nation_array.player_recno )
- nation_array[nationRecno]->is_allied_with_player = 1;
- }
- //------- End of function NationBase::form_alliance_treaty -------//
- //------- Begin of function NationBase::end_treaty ------//
- //
- // <int> withNationRecno - recno of the nation which ends treaty
- // with this nation. If it's an alliance treaty,
- // allied nations with break treaty with
- // this nation.
- //
- // <int> newStatus - the new status after breaking the treaty.
- //
- void NationBase::end_treaty(int withNationRecno,int newStatus)
- {
- //----- decrease reputation when terminating a treaty -----//
- Nation* withNation = nation_array[withNationRecno];
- if( withNation->reputation > 0 )
- {
- int curStatus = get_relation_status(withNationRecno);
- if( curStatus == TALK_END_FRIENDLY_TREATY )
- change_reputation( -withNation->reputation * 10 / 100 );
- else
- change_reputation( -withNation->reputation * 20 / 100 );
- }
- //------- reset good_relation_duration_rating -----//
- if( newStatus <= NATION_NEUTRAL )
- {
- get_relation(withNationRecno)->good_relation_duration_rating = (float) 0;
- withNation->get_relation(nation_recno)->good_relation_duration_rating = (float) 0;
- }
- //------- set new relation status --------//
- set_relation_status(withNationRecno, newStatus);
- //------ set is_allied_with_player -------//
- if( withNationRecno == nation_array.player_recno )
- is_allied_with_player = 0;
- if( nation_recno == nation_array.player_recno )
- nation_array[withNationRecno]->is_allied_with_player = 0;
- }
- //------- End of function NationBase::end_treaty -------//
- //------- Begin of function NationBase::set_trade_treaty ------//
- //
- // <int> nationRecno - recno of the nation to change the trade allow flag
- //
- void NationBase::set_trade_treaty(int nationRecno, char treatyFlag)
- {
- err_when( nation_recno==nationRecno ); // cannot set trade treaty with oneself
- get_relation(nationRecno)->trade_treaty = treatyFlag;
- nation_array[nationRecno]->get_relation(nation_recno)->trade_treaty = treatyFlag;
- }
- //------- End of function NationBase::set_trade_treaty -------//
- //------- Begin of function NationBase::establish_contact ------//
- //
- // <int> nationRecno - recno of the nation to establish contact with
- //
- void NationBase::establish_contact(int nationRecno)
- {
- get_relation(nationRecno)->has_contact = 1;
- nation_array[nationRecno]->get_relation(nation_recno)->has_contact = 1;
- }
- //------- End of function NationBase::establish_contact -------//
- //------- Begin of function NationBase::being_attacked ------//
- //
- // <int> attackNationRecno - recno of the nation that does the attack.
- //
- void NationBase::being_attacked(int attackNationRecno)
- {
- if( nation_array.is_deleted(attackNationRecno) || attackNationRecno==nation_recno )
- return;
- //--- if it is an accidential attack (e.g. bullets attack with spreading damages) ---//
- Nation* attackNation = nation_array[attackNationRecno];
- if( attackNation->get_relation(nation_recno)->should_attack==0 )
- return;
- //--- check if there a treaty between these two nations ---//
- NationRelation* nationRelation = get_relation(attackNationRecno);
- if( nationRelation->status != NATION_HOSTILE )
- {
- //--- if this nation (the one being attacked) has a higher than 0 reputation, the attacker's reputation will decrease ---//
- if( reputation > 0 )
- attackNation->change_reputation( -reputation * 40 / 100 );
- nationRelation->started_war_on_us_count++; // how many times this nation has started a war with us, the more the times the worse this nation is.
- if( nationRelation->status == NATION_ALLIANCE ||
- nationRelation->status == NATION_FRIENDLY )
- {
- attackNation->end_treaty(nation_recno, NATION_HOSTILE); // the attacking nation abruptly terminates the treaty with us, not we terminate the treaty with them, so attackNation->end_treaty() should be called instead of end_treaty()
- }
- else
- {
- set_relation_status(attackNationRecno, NATION_HOSTILE);
- }
- }
- //---- reset the inter-national peace days counter ----//
- nation_array.nation_peace_days = 0;
- }
- //------- End of function NationBase::being_attacked -------//
- //------- Begin of function NationBase::disp_nation_color ------//
- //
- // Display the color of the nation in a rectangular box.
- //
- void NationBase::disp_nation_color(int x, int y)
- {
- vga.active_buf->bar( x, y-2, x+12, y+10, nation_color );
- vga.active_buf->rect( x, y-2, x+12, y+10, 1, nation_color+2 );
- }
- //------- End of function NationBase::disp_nation_color -------//
- //------- Begin of function NationBase::trade_rating ------//
- //
- // Return a rating from 0 to 100 telling the significance of
- // trading with the specific nation in this nation's regard.
- //
- int NationBase::trade_rating(int nationRecno)
- {
- // use an absolute value 5000 as the divider.
- int tradeRating1 = 100 * (int) total_year_trade(nationRecno) / 5000;
- int tradeRating2 = 50 * (int) nation_array[nationRecno]->get_relation(nation_recno)->last_year_import[IMPORT_TOTAL] / (int) (last_year_income+1) +
- 50 * (int) get_relation(nationRecno)->last_year_import[IMPORT_TOTAL] / (int) (last_year_expense+1);
- return max(tradeRating1, tradeRating2);
- }
- //------- End of function NationBase::trade_rating -------//
- //------- Begin of function NationBase::revealed_by_phoenix ------//
- //
- // Whether the area is revealed by phoenix of the nation or not.
- //
- // <int> xLoc, yLoc - the location
- //
- int NationBase::revealed_by_phoenix(int xLoc, int yLoc)
- {
- Unit* unitPtr;
- int effectiveRange = unit_res[UNIT_PHOENIX]->visual_range;
- for( int i=unit_array.size() ; i>0 ; i-- )
- {
- if( unit_array.is_deleted(i) )
- continue;
- unitPtr = unit_array[i];
- if( unitPtr->unit_id == UNIT_PHOENIX &&
- unitPtr->nation_recno == nation_recno )
- {
- if( m.points_distance( xLoc, yLoc,
- unitPtr->next_x_loc(), unitPtr->next_y_loc() ) <= effectiveRange )
- {
- return 1;
- }
- }
- }
- return 0;
- }
- //------- End of function NationBase::revealed_by_phoenix -------//
- //------- Begin of function NationBase::total_tech_level -------//
- //
- // The sum of the tech levels of weapons that this nation possesses.
- //
- // [int] unitClass - only calculate total tech levels of this
- // unit class. (default: 0, any classes)
- //
- int NationBase::total_tech_level(int unitClass)
- {
- TechInfo* techInfo;
- int techLevel, totalTechLevel=0;
- for( int i=1 ; i<=tech_res.tech_count ; i++ )
- {
- techInfo = tech_res[i];
- techLevel = techInfo->get_nation_tech_level(nation_recno);
- if( techLevel > 0 )
- {
- if( !unitClass ||
- (unit_res[techInfo->unit_id]->unit_class == unitClass) )
- {
- totalTechLevel += techLevel;
- }
- }
- }
- return totalTechLevel;
- }
- //-------- End of function NationBase::total_tech_level -------//
- //---------- Begin of function NationBase::civilian_killed --------//
- //
- // This function is called when civilian units are killed and this
- // nation either killed the civilian units or this nation's civilian
- // units are killed.
- //
- // <int> civilianRaceId - the race id. of the civilian unit killed
- // 0 - all races, when a Caravan is killed, 0 will
- // be passed, the loyalty of all races will be decreased.
- //
- // <int> isAttacker - 1 if the nation is the offensive attacker.
- // 0 if the nation that suffers the atttack.
- //
- void NationBase::civilian_killed(int civilianRaceId, int isAttacker)
- {
- if( isAttacker )
- {
- change_all_people_loyalty(-3, civilianRaceId);
- if( civilianRaceId==0 ) // a caravan
- change_reputation(-(float)10);
- else
- change_reputation(-(float)1);
- }
- else
- {
- change_all_people_loyalty(-1, civilianRaceId);
- if( civilianRaceId==0 ) // a caravan
- change_reputation(-(float)3);
- else
- change_reputation(-(float)0.3);
- }
- }
- //----------- End of function NationBase::civilian_killed ---------//
- //--------- Begin of function NationBase::succeed_king --------//
- //
- // Appoint a unit to succeed the king who has died.
- //
- // The loyalty of the people in the natino may change due
- // to the succession.
- //
- void NationBase::succeed_king(int kingUnitRecno)
- {
- Unit* newKing = unit_array[kingUnitRecno];
- err_when( newKing->skill.combat_level <= 0 );
- int newKingLeadership=0;
- if( newKing->skill.skill_id == SKILL_LEADING )
- newKingLeadership = newKing->skill.skill_level;
- newKingLeadership = max( 20, newKingLeadership ); // give the king a minimum level of leadership
- //----- set the common loyalty change for all races ------//
- int loyaltyChange=0;
- if( newKingLeadership < king_leadership )
- loyaltyChange = (newKingLeadership-king_leadership)/2;
- if( newKing->rank_id != RANK_GENERAL )
- loyaltyChange -= 20;
- //---- update loyalty of units in this nation ----//
- Unit* unitPtr;
- int i;
- for( i=unit_array.size() ; i>0 ; i-- )
- {
- if( unit_array.is_deleted(i) )
- continue;
- if( i==king_unit_recno || i==kingUnitRecno )
- continue;
- unitPtr = unit_array[i];
- if( unitPtr->nation_recno != nation_recno )
- continue;
- //--------- update loyalty change ----------//
- unitPtr->change_loyalty( loyaltyChange +
- succeed_king_loyalty_change(unitPtr->race_id, newKing->race_id, race_id) );
- }
- //---- update loyalty of units in camps ----//
- Firm* firmPtr;
- for( i=firm_array.size() ; i>0 ; i-- )
- {
- if( firm_array.is_deleted(i) )
- continue;
- firmPtr = firm_array[i];
- if( firmPtr->nation_recno != nation_recno )
- continue;
- //------ process military camps and seat of power -------//
- if( firmPtr->firm_id == FIRM_CAMP || firmPtr->firm_id == FIRM_BASE )
- {
- Worker* workerPtr = firmPtr->worker_array;
- for(int j=firmPtr->worker_count-1 ; j>=0 ; j--, workerPtr++ )
- {
- //--------- update loyalty change ----------//
- workerPtr->change_loyalty( loyaltyChange +
- succeed_king_loyalty_change(workerPtr->race_id, newKing->race_id, race_id ) );
- }
- }
- }
- //---- update loyalty of town people ----//
- Town* townPtr;
- for( i=town_array.size() ; i>0 ; i-- )
- {
- if( town_array.is_deleted(i) )
- continue;
- townPtr = town_array[i];
- if( townPtr->nation_recno != nation_recno )
- continue;
- for(int raceId=1 ; raceId<=MAX_RACE ; raceId++ )
- {
- if( townPtr->race_pop_array[raceId-1]==0 )
- continue;
- //------ update loyalty now ------//
- townPtr->change_loyalty(raceId, (float) loyaltyChange +
- succeed_king_loyalty_change( raceId, newKing->race_id, race_id ) );
- }
- }
- //------- add news --------//
- news_array.new_king(nation_recno, kingUnitRecno);
- //-------- set the new king now ------//
- set_king(kingUnitRecno, 0); // 0-not the first king, it is a succession
- //------ if the new king is a spy -------//
- if( newKing->spy_recno )
- {
- Spy* spyPtr = spy_array[newKing->spy_recno];
- if( newKing->true_nation_recno() == nation_recno ) // if this is your spy
- spyPtr->drop_spy_identity();
- else
- spyPtr->think_become_king();
- err_when( newKing->rank_id==RANK_KING && newKing->spy_recno ); // it can't still be a spy when it asscends as the king
- }
- }
- //----------- End of function NationBase::succeed_king ---------//
- //------ Begin of static function succeed_king_loyalty_change -----//
- //
- // Return the amount of loyalty should be changed.
- //
- static int succeed_king_loyalty_change(int thisRaceId, int newKingRaceId, int oldKingRaceId)
- {
- #define SAME_RACE_LOYALTY_INC 20
- #define DIFFERENT_RACE_LOYALTY_DEC 30
- //----- the races of the new and old kings are different ----//
- if( newKingRaceId != oldKingRaceId )
- {
- //--- if this unit's race is the same as the new king ---//
- if( thisRaceId == newKingRaceId )
- return SAME_RACE_LOYALTY_INC;
- //--- if this unit's race is the same as the old king ---//
- else if( thisRaceId == oldKingRaceId )
- return DIFFERENT_RACE_LOYALTY_DEC;
- }
- return 0;
- }
- //-------- End of static function succeed_king_loyalty_change ------//
- //--------- Begin of function NationBase::has_people --------//
- //
- // Whether the nation has any people (but not counting the king).
- // If no, then the nation is going to end.
- //
- int NationBase::has_people()
- {
- return all_population() > 0;
- }
- //----------- End of function NationBase::has_people ---------//
- //--------- Begin of function NationBase::surrender --------//
- //
- // This nation surrenders.
- //
- // <int> toNationRecno - the recno of the nation this nation
- // surrenders to.
- //
- void NationBase::surrender(int toNationRecno)
- {
- news_array.nation_surrender(nation_recno, toNationRecno);
- //---- the king demote himself to General first ----//
- if( king_unit_recno )
- {
- unit_array[king_unit_recno]->set_rank(RANK_GENERAL);
- king_unit_recno = 0;
- }
- //------- if the player surrenders --------//
- if( nation_recno==nation_array.player_recno )
- game.game_end(0, 1, toNationRecno);
- //--- hand over the entire nation to another nation ---//
- hand_over_to(toNationRecno);
- }
- //----------- End of function NationBase::surrender ---------//
- //--------- Begin of function NationBase::defeated --------//
- //
- // This nation is defeated.
- //
- void NationBase::defeated()
- {
- //---- if the defeated nation is the player's nation ----//
- if( nation_recno == nation_array.player_recno )
- {
- game.game_end(0, 1); // the player lost the game
- }
- else // AI and remote players
- {
- news_array.nation_destroyed(nation_recno);
- }
- //---- delete this nation from nation_array ----//
- nation_array.del_nation(nation_recno);
- }
- //----------- End of function NationBase::defeated ---------//
- //------- Begin of function NationBase::change_all_people_loyalty ------//
- //
- // Change the loyalty of all the people in your nation.
- //
- // <int> loyaltyChange - degree of loyalty change
- // [int] raceId - if this is given, then only people of this race
- // will be affected. (default: 0)
- //
- void NationBase::change_all_people_loyalty(int loyaltyChange, int raceId)
- {
- //---- update loyalty of units in this nation ----//
- Unit* unitPtr;
- int i;
- for( i=unit_array.size() ; i>0 ; i-- )
- {
- if( unit_array.is_deleted(i) )
- continue;
- if( i==king_unit_recno )
- continue;
- unitPtr = unit_array[i];
- if( unitPtr->nation_recno != nation_recno )
- continue;
- //--------- update loyalty change ----------//
- if( !raceId || unitPtr->race_id == raceId )
- unitPtr->change_loyalty(loyaltyChange);
- }
- //---- update loyalty of units in camps ----//
- Firm* firmPtr;
- for( i=firm_array.size() ; i>0 ; i-- )
- {
- if( firm_array.is_deleted(i) )
- continue;
- firmPtr = firm_array[i];
- if( firmPtr->nation_recno != nation_recno )
- continue;
- //------ process military camps and seat of power -------//
- if( firmPtr->firm_id == FIRM_CAMP || firmPtr->firm_id == FIRM_BASE )
- {
- Worker* workerPtr = firmPtr->worker_array;
- for(int j=firmPtr->worker_count-1 ; j>=0 ; j--, workerPtr++ )
- {
- if( !raceId || workerPtr->race_id == raceId )
- workerPtr->change_loyalty(loyaltyChange);
- }
- }
- }
- //---- update loyalty of town people ----//
- Town* townPtr;
- for( i=town_array.size() ; i>0 ; i-- )
- {
- if( town_array.is_deleted(i) )
- continue;
- townPtr = town_array[i];
- if( townPtr->nation_recno != nation_recno )
- continue;
- //--------------------------------------//
- if( raceId ) // decrease loyalty of a specific race
- {
- if( townPtr->race_pop_array[raceId-1] > 0 )
- townPtr->change_loyalty(raceId, (float) loyaltyChange);
- }
- else // decrease loyalty of all races
- {
- for(int j=0 ; j<MAX_RACE ; j++ )
- {
- if( townPtr->race_pop_array[j]==0 )
- continue;
- townPtr->change_loyalty(j+1, (float) loyaltyChange);
- }
- }
- }
- }
- //------- End of function NationBase::change_all_people_loyalty -------//
- //------- Begin of function NationBase::total_year_trade ------//
- //
- // Return the total trade (import + export) with the specific
- // trade in the last year.
- //
- float NationBase::total_year_trade(int nationRecno)
- {
- return get_relation(nationRecno)->last_year_import[IMPORT_TOTAL] +
- nation_array[nationRecno]->get_relation(nation_recno)->last_year_import[IMPORT_TOTAL];
- }
- //------- End of function NationBase::total_year_trade -------//
- //---------- Begin of function NationBase::check_win --------//
- //
- // Check if the player has won the game.
- //
- void NationBase::check_win()
- {
- int hasWon = goal_destroy_nation_achieved() ||
- goal_destroy_monster_achieved() ||
- goal_population_achieved() ||
- goal_economic_score_achieved() ||
- goal_total_score_achieved();
- if( !hasWon )
- return;
- //--------------------------------------//
- game.game_end(nation_recno, 0); // if the player achieves the goal, the player wins, if one of the other kingdoms achieves the goal, it wins.
- }
- //----------- End of function NationBase::check_win ---------//
- //---------- Begin of function NationBase::check_lose --------//
- //
- // Check if the player has lost the game.
- //
- // If the player still hasn't selected a unit to succeed the
- // died king, declare defeated if the all units are killed.
- //
- void NationBase::check_lose()
- {
- //---- if the king of this nation is dead and it has no people left ----//
- if( !king_unit_recno && !has_people() )
- defeated();
- }
- //----------- End of function NationBase::check_lose ---------//
- //---------- Begin of function NationBase::give_tribute --------//
- //
- // Give tribute or aid to a nation.
- //
- // <int> toNationRecno - give tribute to this nation
- // <int> tributeAmt - the amount of the tribute
- //
- void NationBase::give_tribute(int toNationRecno, int tributeAmt)
- {
- Nation* toNation = nation_array[toNationRecno];
- add_expense( EXPENSE_TRIBUTE, (float) tributeAmt );
- toNation->add_income( INCOME_TRIBUTE, (float) tributeAmt );
- NationRelation* nationRelation = get_relation(toNationRecno);
- nationRelation->last_give_gift_date = info.game_date;
- nationRelation->total_given_gift_amount += tributeAmt;
- //---- set the last rejected date so it won't request or give again soon ----//
- nationRelation->last_talk_reject_date_array[TALK_GIVE_AID-1] = 0;
- nationRelation->last_talk_reject_date_array[TALK_DEMAND_AID-1] = 0;
- nationRelation->last_talk_reject_date_array[TALK_GIVE_TRIBUTE-1] = 0;
- nationRelation->last_talk_reject_date_array[TALK_DEMAND_TRIBUTE-1] = 0;
- NationRelation* nationRelation2 = toNation->get_relation(nation_recno);
- nationRelation2->last_talk_reject_date_array[TALK_GIVE_AID-1] = 0;
- nationRelation2->last_talk_reject_date_array[TALK_DEMAND_AID-1] = 0;
- nationRelation2->last_talk_reject_date_array[TALK_GIVE_TRIBUTE-1] = 0;
- nationRelation2->last_talk_reject_date_array[TALK_DEMAND_TRIBUTE-1] = 0;
- }
- //----------- End of function NationBase::give_tribute ---------//
- //---------- Begin of function NationBase::give_tech --------//
- //
- // Give tribute or aid to a nation.
- //
- // <int> toNationRecno - give tribute to this nation
- // <int> techId - id. of the technology
- // <int> techVersion - version of the technology
- //
- void NationBase::give_tech(int toNationRecno, int techId, int techVersion)
- {
- Nation* toNation = nation_array[toNationRecno];
- int curVersion = tech_res[techId]->get_nation_tech_level(toNationRecno);
- if( curVersion < techVersion )
- tech_res[techId]->set_nation_tech_level( toNationRecno, techVersion );
- NationRelation* nationRelation = get_relation(toNationRecno);
- nationRelation->last_give_gift_date = info.game_date;
- nationRelation->total_given_gift_amount += (techVersion-curVersion) * 500; // one version level is worth $500
- //---- set the last rejected date so it won't request or give again soon ----//
- nationRelation->last_talk_reject_date_array[TALK_GIVE_TECH-1] = 0;
- nationRelation->last_talk_reject_date_array[TALK_DEMAND_TECH-1] = 0;
- NationRelation* nationRelation2 = toNation->get_relation(nation_recno);
- nationRelation2->last_talk_reject_date_array[TALK_GIVE_TECH-1] = 0;
- nationRelation2->last_talk_reject_date_array[TALK_DEMAND_TECH-1] = 0;
- }
- //----------- End of function NationBase::give_tech ---------//
- //----- Begin of function NationBase::base_town_count_in_region -----//
- //
- // Return the number of base towns in the given region.
- //
- int NationBase::base_town_count_in_region(int regionId)
- {
- // ###### patch begin Gilbert 16/3 #######//
- // regionStatId may be zero
- int regionStatId = region_array[regionId]->region_stat_id;
- if( regionStatId )
- {
- return region_array.get_region_stat2(regionStatId)->
- base_town_nation_count_array[nation_recno-1];
- }
- else if( region_array[regionId]->region_size < STD_TOWN_LOC_WIDTH*STD_TOWN_LOC_HEIGHT)
- {
- return 0; // not enough to build any town
- }
- else
- {
- int townCount = 0;
- for( int townRecno = town_array.size(); townRecno > 0; --townRecno )
- {
- if( town_array.is_deleted(townRecno) )
- continue;
- Town *townPtr = town_array[townRecno];
- if( townPtr->region_id == regionId && townPtr->nation_recno == nation_recno )
- townCount++;
- }
- return townCount == 0;
- }
- // ###### patch end Gilbert 16/3 #######//
- }
- //------ End of function NationBase::base_town_count_in_region -----//
- //----- Begin of function NationBase::peace_duration_str -----//
- //
- char* NationBase::peace_duration_str()
- {
- int peaceDays = peaceful_days();
- int peaceYear = peaceDays / 365;
- int peaceMonth = (peaceDays - peaceYear * 365) / 30;
- static String str;
- str = "";
- if( peaceYear > 0 )
- {
- str += peaceYear;
- str += translate.process( peaceYear>1 ? (char*)" years" : (char*)" year" );
- str += translate.process( (char*)" and " );
- }
- str += peaceMonth;
- str += translate.process( peaceMonth>1 ? (char*)" months" : (char*)" month" );
- return str;
- }
- //------ End of function NationBase::peace_duration_str -----//
- //----- Begin of function NationBase::true_income_365days -----//
- //
- // Return the total income of the nation, excluding cheats.
- //
- float NationBase::true_income_365days()
- {
- float curYearIncome=(float)0, lastYearIncome=(float)0;
- for( int i=0 ; i<INCOME_TYPE_COUNT-1 ; i++ ) // -1 to exclude cheat
- {
- curYearIncome += cur_year_income_array[i];
- lastYearIncome += last_year_income_array[i];
- }
- return lastYearIncome * (365-info.year_day) / 365 + curYearIncome;
- }
- //------ End of function NationBase::true_income_365days -----//
- //----- Begin of function NationBase::update_nation_rating -----//
- //
- void NationBase::update_nation_rating()
- {
- population_rating = get_population_rating();
- economic_rating = get_economic_rating();
- overall_rating = get_overall_rating();
- }
- //------ End of function NationBase::update_nation_rating -----//
- //----- Begin of function NationBase::get_population_rating -----//
- //
- int NationBase::get_population_rating()
- {
- return all_population();
- }
- //------ End of function NationBase::get_population_rating -----//
- //----- Begin of function NationBase::get_economic_rating -----//
- //
- int NationBase::get_economic_rating()
- {
- return (int) cash / 300 +
- (int) true_income_365days()/2 +
- (int) true_profit_365days();
- }
- //------ End of function NationBase::get_economic_rating -----//
- //----- Begin of function NationBase::get_overall_rating -----//
- //
- int NationBase::get_overall_rating()
- {
- return 33*population_rating/500+
- 33*military_rating/200+
- 33*economic_rating/10000;
- }
- //------ End of function NationBase::get_overall_rating -----//
- //----- Begin of function NationBase::population_rank_rating -----//
- //
- int NationBase::population_rank_rating()
- {
- if( nation_array.max_population_rating==0 )
- return 0;
- return 100 * population_rating / nation_array.max_population_rating;
- }
- //------ End of function NationBase::population_rank_rating -----//
- //----- Begin of function NationBase::military_rank_rating -----//
- //
- int NationBase::military_rank_rating()
- {
- if( nation_array.max_military_rating==0 )
- return 0;
- return 100 * military_rating / nation_array.max_military_rating;
- }
- //------ End of function NationBase::military_rank_rating -----//
- //----- Begin of function NationBase::economic_rank_rating -----//
- //
- int NationBase::economic_rank_rating()
- {
- if( nation_array.max_economic_rating==0 )
- return 0;
- return 100 * economic_rating / nation_array.max_economic_rating;
- }
- //------ End of function NationBase::economic_rank_rating -----//
- //----- Begin of function NationBase::reputation_rank_rating -----//
- //
- int NationBase::reputation_rank_rating()
- {
- if( nation_array.max_reputation==0 )
- return 0;
- return 100 * (int) reputation / nation_array.max_reputation;
- }
- //------ End of function NationBase::reputation_rank_rating -----//
- //----- Begin of function NationBase::kill_monster_rank_rating -----//
- //
- int NationBase::kill_monster_rank_rating()
- {
- if( nation_array.max_kill_monster_score==0 )
- return 0;
- if( config.monster_type == OPTION_MONSTER_NONE )
- return 0;
- return 100 * (int) kill_monster_score / nation_array.max_kill_monster_score;
- }
- //------ End of function NationBase::kill_monster_rank_rating -----//
- //----- Begin of function NationBase::overall_rank_rating -----//
- //
- int NationBase::overall_rank_rating()
- {
- if( nation_array.max_overall_rating==0 )
- return 0;
- return 100 * overall_rating / nation_array.max_overall_rating;
- }
- //------ End of function NationBase::overall_rank_rating -----//
- //------- Begin of function NationBase::goal_destroy_nation_achieved --------//
- int NationBase::goal_destroy_nation_achieved()
- {
- return nation_array.nation_count==1;
- }
- //------- End of function NationBase::goal_destroy_nation_achieved --------//
- //------- Begin of function NationBase::goal_destroy_monster_achieved --------//
- int NationBase::goal_destroy_monster_achieved()
- {
- if( !config.goal_destroy_monster ) // this is not one of the required goals.
- return 0;
- if( config.monster_type == OPTION_MONSTER_NONE )
- return 0;
- //------- when all monsters have been killed -------//
- if( firm_res[FIRM_MONSTER]->total_firm_count == 0 &&
- unit_res.mobile_monster_count == 0 )
- {
- Nation* nationPtr;
- float maxScore=(float)0;
- for( int i=nation_array.size() ; i>0 ; i-- )
- {
- if( nation_array.is_deleted(i) )
- continue;
- nationPtr = nation_array[i];
- if( nationPtr->kill_monster_score > maxScore )
- maxScore = nationPtr->kill_monster_score;
- }
- //-- if this nation is the one that has destroyed most monsters, it wins, otherwise it loses --//
- return maxScore == kill_monster_score;
- }
- return 0;
- }
- //------- End of function NationBase::goal_destroy_monster_achieved --------//
- //------- Begin of function NationBase::goal_population_achieved --------//
- int NationBase::goal_population_achieved()
- {
- if( !config.goal_population_flag ) // this is not one of the required goals.
- return 0;
- return all_population() >= config.goal_population;
- }
- //------- End of function NationBase::goal_population_achieved --------//
- //------ Begin of function NationBase::goal_economic_score_achieved ------//
- int NationBase::goal_economic_score_achieved()
- {
- if( !config.goal_economic_score_flag )
- return 0;
- info.set_rank_data(0); // 0-set all nations, not just those that have contact with us
- return info.get_rank_score(3,nation_recno) >= config.goal_economic_score;
- }
- //------- End of function NationBase::goal_economic_score_achieved -------//
- //------ Begin of function NationBase::goal_total_score_achieved -------//
- int NationBase::goal_total_score_achieved()
- {
- if( !config.goal_total_score_flag )
- return 0;
- info.set_rank_data(0); // 0-set all nations, not just those that have contact with us
- return info.get_total_score(nation_recno) >= config.goal_total_score;
- }
- //------- End of function NationBase::goal_total_score_achieved --------//
- //----- Begin of function NationBase::set_auto_collect_tax_loyalty -----//
- //
- void NationBase::set_auto_collect_tax_loyalty(int loyaltyLevel)
- {
- auto_collect_tax_loyalty = loyaltyLevel;
- if( loyaltyLevel && auto_grant_loyalty >= auto_collect_tax_loyalty )
- {
- auto_grant_loyalty = auto_collect_tax_loyalty-10;
- }
- }
- //------ End of function NationBase::set_auto_collect_tax_loyalty -----//
- //----- Begin of function NationBase::set_auto_grant_loyalty -----//
- //
- void NationBase::set_auto_grant_loyalty(int loyaltyLevel)
- {
- auto_grant_loyalty = loyaltyLevel;
- if( loyaltyLevel && auto_grant_loyalty >= auto_collect_tax_loyalty )
- {
- auto_collect_tax_loyalty = auto_grant_loyalty+10;
- if( auto_collect_tax_loyalty > 100 )
- auto_collect_tax_loyalty = 0; // disable auto collect tax if it's over 100
- }
- }
- //------ End of function NationBase::set_auto_grant_loyalty -----//
- //----- Begin of function NationRelation::status_duration_str -----//
- //
- char* NationRelation::status_duration_str()
- {
- int statusDays = info.game_date - last_change_status_date;
- int statusYear = statusDays / 365;
- int statusMonth = (statusDays - statusYear * 365) / 30;
- static String str;
- str = "";
- if( statusYear > 0 )
- {
- str += statusYear;
- str += translate.process( statusYear>1 ? (char*)" years" : (char*)" year" );
- str += translate.process( (char*)" and " );
- }
- str += statusMonth;
- str += translate.process( statusMonth>1 ? (char*)" months" : (char*)" month" );
- return str;
- }
- //------ End of function NationRelation::status_duration_str -----//
|