/* * 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 : OTOWNINDP.CPP //Description : Independent town thining #include #include #include #include #include #include #include #include #include #include #include #include #include //------- Begin of function Town::think_independent_town --------// // // Independent town thinking. // void Town::think_independent_town() { if( rebel_recno ) // if this is a rebel town, its AI will be executed in Rebel::think_town_action() return; #if defined(DEBUG) && defined(ENABLE_LOG) String logStr; logStr = "begin Town::think_independent_town, town_recno="; logStr += town_recno; LOG_MSG(logStr); #endif //---- think about toggling town links ----// if( info.game_date%15 == town_recno%15 ) { LOG_MSG(" Town::think_independent_set_link"); think_independent_set_link(); LOG_MSG(m.get_random_seed() ); } //---- think about independent units join existing nations ----// if( info.game_date%60 == town_recno%60 ) { LOG_MSG(" Town::think_independent_unit_join_nation"); think_independent_unit_join_nation(); LOG_MSG(m.get_random_seed() ); } //----- think about form a new nation -----// if( info.game_date%365 == town_recno%365 ) { LOG_MSG(" Town::think_independent_form_new_nation"); think_independent_form_new_nation(); LOG_MSG(m.get_random_seed() ); } LOG_MSG("end Town::think_independent_town"); LOG_MSG(m.get_random_seed()); } //-------- End of function Town::think_independent_town ---------// //------- Begin of function Town::think_independent_set_link --------// // // Independent town thinking. // void Town::think_independent_set_link() { //---- think about working for foreign firms ------// int linkStatus; Firm* firmPtr; for(int i=0; ifirm_id == FIRM_CAMP ) // a town cannot change its status with a military camp continue; //---- think about the link status ----// linkStatus = 0; if( firmPtr->nation_recno == 0 ) // if the firm is also an independent firm linkStatus = 1; if( average_resistance(firmPtr->nation_recno) <= INDEPENDENT_LINK_RESISTANCE ) linkStatus = 1; //---- set the link status -------// toggle_firm_link( i+1, linkStatus, COMMAND_AI ); } ai_link_checked = 1; } //-------- End of function Town::think_independent_set_link ---------// //------ Begin of function Town::think_independent_form_new_nation ------// // // Independent town thinking. // int Town::think_independent_form_new_nation() { if( m.random(10) > 0 ) // 1/10 chance to set up a new nation. return 0; //-------- check if the town is big enough -------// if( population < 30 ) return 0; //---- don't form if the world is already densely populated ----// if( nation_array.all_nation_population > 60 * MAX_NATION ) return 0; //----------------------------------------------// if( !nation_array.can_form_new_ai_nation() ) return 0; //----------------------------------------------// return form_new_nation(); } //------ End of function Town::think_independent_form_new_nation ------// //--------- Begin of function Town::form_new_nation ---------// // // This independent town forms a new nation. // // Return: // int Town::form_new_nation() { err_when( nation_recno ); if( !nation_array.can_form_new_ai_nation() ) return 0; //----- determine the race with most population -----// int maxPop=0, raceId=0; int i; for( i=0 ; i maxPop ) { maxPop = race_pop_array[i]; raceId = i+1; } } err_when( !raceId ); //---- create the king of the new nation ----// int unitId = race_res[raceId]->basic_unit_id; int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results SpriteInfo* spriteInfo = sprite_res[unit_res[unitId]->sprite_id]; if( !world.locate_space( xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height ) ) return 0; //--------- create a new nation ---------// int nationRecno = nation_array.new_nation( NATION_AI, raceId, nation_array.random_unused_color() ); err_when( !nationRecno ); //-------- create the king --------// int kingUnitRecno = unit_array.add_unit( unitId, nationRecno, RANK_KING, 100, xLoc, yLoc ); Unit* kingUnit = unit_array[kingUnitRecno]; kingUnit->skill.skill_id = SKILL_LEADING; kingUnit->skill.skill_level = 50+m.random(51); kingUnit->set_combat_level(70+m.random(31)); nation_array[nationRecno]->set_king(kingUnitRecno, 1); // 1-this is the first king of the nation dec_pop(raceId, 0); // 0-the unit doesn't have a job //------ set the nation of the rebel town -----// err_when( rebel_recno ); // rebel has its own function in Rebel, this shouldn't be called set_nation(nationRecno); // set the town at last because set_nation() will delete the Town object //------ increase the loyalty of the town -----// for( i=0 ; iset_nation_tech_level(nationRecno, 1); break; case 2: // random additional cash nationPtr->cash += m.random(5000); break; case 3: // random additional food nationPtr->food += m.random(5000); break; case 4: // random additional skilled units mobileCount = m.random(5)+1; for( i=0 ; i0 ; i++ ) // 0-don't recruit spies { int unitRecno = mobilize_town_people(raceId, 1, 0); // 1-dec pop, 0-don't mobilize spies if( unitRecno ) { Unit* unitPtr = unit_array[unitRecno]; //------- randomly set a skill -------// int skillId = m.random(MAX_TRAINABLE_SKILL)+1; int loopCount=0; // no spying skill while( skillId==SKILL_SPYING ) // no spy skill as skill_id can't be set as SKILL_SPY, for spies, spy_recno must be set instead { if( ++skillId > MAX_TRAINABLE_SKILL ) skillId = 1; err_when( ++loopCount > 100 ); } unitPtr->skill.skill_id = skillId; unitPtr->skill.skill_level = 50 + m.random(50); unitPtr->set_combat_level( 50 + m.random(50) ); } else break; } break; } return nationRecno; } //----------- End of function Town::form_new_nation ---------// //---- Begin of function Town::think_independent_unit_join_nation ----// // // Think having independent units joining existing nations. // int Town::think_independent_unit_join_nation() { if( jobless_population==0 ) return 0; independent_unit_join_nation_min_rating -= 2; // make it easier to join nation everytime it's called // -2 each time, adding of 30 after a unit has been recruited and calling it once every 2 months make it a normal rate of joining once a year per town //------ think about which nation to turn towards -----// int i, bestNationRecno=0, curRating, raceId, bestRaceId=0; int bestRating=independent_unit_join_nation_min_rating; Nation *nationPtr; // ###### patch begin Gilbert 16/3 ########// // #ifdef AMPLUS if( region_array[region_id]->region_stat_id == 0) return 0; // #endif // ###### patch end Gilbert 16/3 ########// RegionStat* regionStat = region_array.get_region_stat(region_id); for( i=nation_array.size() ; i>0 ; i-- ) { if( nation_array.is_deleted(i) ) continue; nationPtr = nation_array[i]; if( !nationPtr->race_id ) continue; if( nationPtr->cash <= 0 ) continue; if( info.game_date < nationPtr->last_independent_unit_join_date + 90 ) // don't join too frequently, at most 3 months a unit continue; //--- only join the nation if the nation has town in the town's region ---// if( regionStat->town_nation_count_array[i-1] == 0 ) continue; //----- calculate the rating of the nation -----// curRating = (int) nationPtr->reputation + nationPtr->overall_rating; if( recruitable_race_pop(nationPtr->race_id, 0) > 0 ) // 0-don't count spies { curRating += 30; raceId = nationPtr->race_id; } else raceId = 0; if( curRating > bestRating ) { bestRating = curRating; bestNationRecno = i; bestRaceId = raceId; } } //--------------------------------------------// if( !bestNationRecno ) return 0; if( !bestRaceId ) bestRaceId = pick_random_race(0, 0); // 0-only pick jobless unit, 0-don't pick spy units if( !bestRaceId ) return 0; if( !independent_unit_join_nation(bestRaceId, bestNationRecno) ) return 0; //--- set a new value to independent_unit_join_nation_min_rating ---// independent_unit_join_nation_min_rating = bestRating + 100 + m.random(30); // reset it to a higher rating if( independent_unit_join_nation_min_rating < 100 ) independent_unit_join_nation_min_rating = 100; return 1; } //----- End of function Town::think_independent_unit_join_nation -----// //---- Begin of function Town::independent_unit_join_nation ----// // // raceId - race id. of the unit // toNationRecno - recno of the nation the unit should turn toward // int Town::independent_unit_join_nation(int raceId, int toNationRecno) { //----- mobilize a villager ----// int unitRecno = mobilize_town_people(raceId, 1, 0); // 1-dec population after mobilizing the unit, 0-don't mobilize spies if( !unitRecno ) return 0; Unit* unitPtr = unit_array[unitRecno]; //----- set the skills of the unit -----// int skillId, skillLevel, combatLevel; switch( m.random(3) ) { case 0: // leaders skillId = SKILL_LEADING; if( m.random(3)==0 ) skillLevel = m.random(100); else skillLevel = m.random(50); combatLevel = skillLevel + m.random(40) - 20; combatLevel = min(combatLevel, 100); combatLevel = max(combatLevel, 10); break; case 1: // peasants skillId = 0; skillLevel = 0; combatLevel = 10 + m.random(10); break; case 2: // skilled units skillId = m.random(MAX_TRAINABLE_SKILL)+1; { int loopCount=0; // no spying skill while( skillId==SKILL_SPYING ) { if( ++skillId > MAX_TRAINABLE_SKILL ) skillId = 1; err_when( ++loopCount > 100 ); } } skillLevel = 10+m.random(80); combatLevel = 10+m.random(30); break; } //--------------------------------------// unitPtr->skill.skill_id = skillId; unitPtr->skill.skill_level = skillLevel; unitPtr->set_combat_level( combatLevel ); //------ change nation now --------// if( !unitPtr->betray(toNationRecno) ) return 0; //---- the unit moves close to the newly joined nation ----// unitPtr->ai_move_to_nearby_town(); //-------- set last_independent_unit_join_date --------// nation_array[toNationRecno]->last_independent_unit_join_date = info.game_date; return 1; } //----- End of function Town::independent_unit_join_nation -----//