1 /*
2  * Seven Kingdoms: Ancient Adversaries
3  *
4  * Copyright 1997,1998 Enlight Software Ltd.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 //Filename    : OF_CAMP2.CPP
22 //Description : Firm Military Camp - AI functions
23 
24 #include <ONATION.h>
25 #include <OINFO.h>
26 #include <OCONFIG.h>
27 #include <OTOWN.h>
28 #include <OSPY.h>
29 #include <OUNIT.h>
30 #include <OF_CAMP.h>
31 
32 //--------- Begin of function FirmCamp::init_derived ---------//
33 
init_derived()34 void FirmCamp::init_derived()
35 {
36 	patrol_unit_count = 0;
37 	coming_unit_count = 0;
38 
39 	ai_capture_town_recno = 0;
40 	ai_recruiting_soldier = 1;
41 }
42 //----------- End of function FirmCamp::init_derived -----------//
43 
44 
45 //--------- Begin of function FirmCamp::process_ai ---------//
46 
process_ai()47 void FirmCamp::process_ai()
48 {
49 	if( info.game_date%15==firm_recno%15 )		// do not call too often as the penalty of accumulation is 10 days
50 		think_use_cash_to_capture();
51 
52 	//------- assign overseer and workers -------//
53 
54 	if( info.game_date%15==firm_recno%15 )		// do not call too often because when an AI action is queued, it will take a while to carry it out
55 		think_recruit();
56 
57 	//---- if this firm is currently trying to capture a town ----//
58 
59 	if( ai_capture_town_recno )
60 	{
61 		should_close_flag = 0;		// disable should_close_flag when trying to capture a firm, should_close_flag is set in process_common_ai()
62 
63 		if( nation_array[nation_recno]->attack_camp_count==0 &&		// only when attack_camp_count==0, the attack mission is complete
64 			 patrol_unit_count==0 )
65 		{
66 			ai_capture_town_recno = 0;
67 			defense_flag = 1;    			// turn it on again after the capturing plan is finished
68 			return;
69 		}
70 
71 //		process_ai_capturing();
72 		return;
73 	}
74 
75 	//--- if the firm is empty and should be closed, sell/destruct it now ---//
76 
77 	if( should_close_flag )
78 	{
79 		if( worker_count==0 )
80 		{
81 			ai_del_firm();
82 			return;
83 		}
84 	}
85 
86 	//----- think about assigning a better commander -----//
87 
88 	if( info.game_date%30==firm_recno%30 )
89 		think_assign_better_commander();
90 
91 	//----- think about changing links to foreign town -----//
92 
93 	if( info.game_date%30==firm_recno%30 )
94 		think_change_town_link();
95 
96 	//------ think about attacking enemies nearby -------//
97 
98 	int checkInterval = 13 - nation_array[nation_recno]->pref_military_development/10;
99 
100 	if( info.game_date%checkInterval == firm_recno%checkInterval )
101 		think_attack_nearby_enemy();
102 
103 	//------ think about capturing independent town -------//
104 
105 	static short interval_days_array[] = { 60, 30, 20, 10 };
106 
107 	int intervalDays = interval_days_array[config.ai_aggressiveness-1];
108 
109 	if( info.game_date%intervalDays == firm_recno%intervalDays )		// do not call too often because when an AI action is queued, it will take a while to carry it out
110 		think_capture();
111 
112 	//---------------------------------------//
113 
114 	if( info.game_date%30 == firm_recno%30 )
115 	{
116 		ai_reset_defense_mode(); // reset defense mode if all soldiers are dead
117 	}
118 }
119 //----------- End of function FirmCamp::process_ai -----------//
120 
121 
122 //--------- Begin of function FirmCamp::ai_reset_defense_mode ---------//
123 
ai_reset_defense_mode()124 void FirmCamp::ai_reset_defense_mode()
125 {
126 	if(ai_status!=CAMP_IN_DEFENSE)
127 		return;
128 
129 	//------------------------------------------------------------//
130 	// reset defense mode if all soldiers are dead
131 	//------------------------------------------------------------//
132 	DefenseUnit *defPtr = defense_array;
133 	Unit	*unitPtr;
134 	int	found=0;
135 
136 	for(int i=0; i<=MAX_WORKER; i++, defPtr++)
137 	{
138 		if(!defPtr->unit_recno)
139 			continue; // empty slot
140 
141 		if(unit_array.is_deleted(defPtr->unit_recno))
142 			continue;
143 
144 		unitPtr = unit_array[defPtr->unit_recno];
145 		if(unitPtr->nation_recno==nation_recno && unitPtr->action_misc==ACTION_MISC_DEFENSE_CAMP_RECNO &&
146 			unitPtr->action_misc_para==firm_recno) // is a soldier of this camp
147 			found++;
148 	}
149 
150 	if(!found)
151 	{
152 		set_employ_worker(1); // all soldiers have died, reset defense mode to employ new workers
153 		memset(defense_array, 0, sizeof(DefenseUnit)*(MAX_WORKER+1));
154 	}
155 }
156 //----------- End of function FirmCamp::ai_reset_defense_mode -----------//
157 
158 
159 //--------- Begin of function FirmCamp::process_ai_capturing ---------//
160 //
161 // This function is called when the AI is in the process of
162 // attacking and capturing the independent town this camp is
163 // linked to.
164 //
process_ai_capturing()165 void FirmCamp::process_ai_capturing()
166 {
167 	err_when( patrol_unit_count <= 0 );		// this function shouldn't be called at all if patrol_unit_count==0
168 	err_when( patrol_unit_count>9 );
169 
170 	if( !ai_capture_town_recno )
171 		return;
172 
173 	if( think_capture_return() )	// if the capturing units should now return to their base.
174 		return;
175 
176 	//--- there are still town defender out there, order idle units to attack them ---//
177 
178 	Unit* unitPtr;
179 	Town* townPtr = town_array[ai_capture_town_recno];
180 
181 	if( townPtr->town_defender_count > 0 )
182 	{
183 		for( int i=patrol_unit_count ; i>0 ; i-- )
184 		{
185 			unitPtr = unit_array[ patrol_unit_array[i-1] ];
186 
187 			if( unitPtr->cur_action == SPRITE_IDLE )
188 				ai_attack_town_defender(unitPtr);
189 		}
190 	}
191 
192 	//--- if the town is still not captured but all mobile town defenders are destroyed, attack the town again ---//
193 
194 	if( townPtr->town_defender_count == 0 )
195 	{
196 		//----- have one of the units attack the town ----//
197 
198 		short unitArray[1];
199 
200 		err_when( patrol_unit_count<=0 );
201 
202 		unitArray[0] = patrol_unit_array[ misc.random(patrol_unit_count) ];
203 
204 		err_when( unit_array.is_deleted(unitArray[0]) );
205 
206 		if( townPtr->nation_recno )
207 			nation_array[nation_recno]->set_relation_should_attack( townPtr->nation_recno, 1, COMMAND_AI );
208 
209 		// ##### patch begin Gilbert 5/8 ######//
210 		unit_array.attack(townPtr->loc_x1, townPtr->loc_y1, 0, unitArray, 1, COMMAND_AI, 0);
211 		// ##### patch end Gilbert 5/8 ######//
212 	}
213 }
214 //----------- End of function FirmCamp::process_ai_capturing -----------//
215 
216 
217 //------ Begin of function FirmCamp::ai_attack_town_defender ------//
218 //
ai_attack_town_defender(Unit * attackerUnit)219 void FirmCamp::ai_attack_town_defender(Unit* attackerUnit)
220 {
221 	int shouldAttackUnit=0;
222 
223 	if( attackerUnit->cur_action == SPRITE_IDLE )
224 		shouldAttackUnit = 1;
225 
226 	else if( attackerUnit->cur_action == SPRITE_ATTACK )
227 	{
228 		//--- if this unit is currently attacking the town, ask it to attack a defender unit ---//
229 
230 		Town* townPtr = town_array[ai_capture_town_recno];
231 
232 		if( attackerUnit->action_x_loc==townPtr->loc_x1 && attackerUnit->action_y_loc==townPtr->loc_y1 )
233 			shouldAttackUnit = 1;
234 	}
235 
236 	if( !shouldAttackUnit )
237 		return;
238 
239 	//---- if there are still town defenders out there ---//
240 
241 	int unitCount = unit_array.size();
242 	int unitRecno = misc.random(unitCount)+1;		// scan randomly
243 	short unitArray[1];
244 	Unit* targetUnit;
245 
246 	for( int i=0 ; i<unitCount ; i++ )
247 	{
248 		if( ++unitRecno > unitCount )
249 			unitRecno = 1;
250 
251 		if( unit_array.is_deleted(unitRecno) )
252 			continue;
253 
254 		targetUnit = unit_array[unitRecno];
255 
256 		if( targetUnit->unit_mode == UNIT_MODE_DEFEND_TOWN &&
257 			 targetUnit->unit_mode_para == ai_capture_town_recno )
258 		{
259 			unitArray[0] = attackerUnit->sprite_recno;
260 
261 			if( targetUnit->nation_recno )
262 				nation_array[nation_recno]->set_relation_should_attack( targetUnit->nation_recno, 1, COMMAND_AI );
263 
264 			// ##### patch begin Gilbert 5/8 ######//
265 			unit_array.attack( targetUnit->next_x_loc(), targetUnit->next_y_loc(),
266 									 0, unitArray, 1, COMMAND_AI, targetUnit->sprite_recno );
267 			// ##### patch end Gilbert 5/8 ######//
268 			break;
269 		}
270 	}
271 }
272 //-------- End of function FirmCamp::ai_attack_town_defender ------//
273 
274 
275 //--------- Begin of function FirmCamp::think_recruit ---------//
276 //
277 // Think about recruiting an overseer and soliders to this base.
278 //
think_recruit()279 void FirmCamp::think_recruit()
280 {
281 	if( patrol_unit_count )		// if there are units of this camp patrolling outside
282 		return;
283 
284 	Nation* nationPtr = nation_array[nation_recno];
285 
286 	ai_recruiting_soldier = 1; 		// the AI is currently trying to recruit soldiers
287 
288 	//---- if there are currently units coming to this firm ----//
289 
290 	if( coming_unit_count > 0 )
291 	{
292 		Unit* unitPtr;
293 
294 		for( int i=0 ; i<coming_unit_count ; i++ )
295 		{
296 			if( unit_array.is_deleted( coming_unit_array[i] ) )
297 				continue;
298 
299 			unitPtr = unit_array[ coming_unit_array[i] ];
300 
301 			//--- check if any of them are still on their way to this firm ---//
302 
303 			if( unitPtr->nation_recno == nation_recno &&
304 				 unitPtr->action_mode == ACTION_ASSIGN_TO_FIRM )
305 			{
306 				//--- if so, do not do anything unit they are all done ---//
307 
308 				return;
309 			}
310 		}
311 
312 		coming_unit_count = 0;
313 	}
314 
315 	//-- if this camp is empty, think about move a whole troop from a useless camp (should_ai_close()==1)
316 
317 	if( !overseer_recno && worker_count==0 &&
318 		 nationPtr->firm_should_close_array[FIRM_CAMP-1] > 0 )
319 	{
320 		FirmCamp *firmCamp, *bestCampPtr=NULL;
321 		int		bestRating=0, curRating;
322 
323 		//--- see if there are any useless camps around and pick the most suitable one ---//
324 
325 		for( int i=nationPtr->ai_camp_count-1 ; i>=0 ; i-- )
326 		{
327 			firmCamp = (FirmCamp*) firm_array[ nationPtr->ai_camp_array[i] ];
328 
329 			err_when( firmCamp->firm_id != FIRM_CAMP );
330 
331 			if( firmCamp->region_id != region_id )
332 				continue;
333 
334 			if( firmCamp->should_close_flag &&
335 				 (firmCamp->overseer_recno || firmCamp->worker_count>0) )
336 			{
337 				curRating = 100 - misc.points_distance( center_x, center_y,
338 								firmCamp->center_x, firmCamp->center_y );
339 
340 				if( curRating > bestRating )
341 				{
342 					bestRating = curRating;
343 					bestCampPtr = firmCamp;
344 				}
345 			}
346 		}
347 
348 		//--------- start the move now -------//
349 
350 		if( bestCampPtr )
351 		{
352 			bestCampPtr->patrol();
353 
354 			if( bestCampPtr->patrol_unit_count==0 )		// there could be chances that there are no some for mobilizing the units
355 				return;
356 
357 			//--- set coming_unit_count for later checking ---//
358 
359 			err_when( sizeof(coming_unit_array) != sizeof(patrol_unit_array) );
360 
361 			memcpy( coming_unit_array, bestCampPtr->patrol_unit_array, sizeof(coming_unit_array) );
362 			coming_unit_count = bestCampPtr->patrol_unit_count;
363 
364 			//---- order the unit to move to this camp now ---//
365 
366 			unit_array.assign(loc_x1, loc_y1, 0, COMMAND_AI, bestCampPtr->patrol_unit_array, bestCampPtr->patrol_unit_count);
367 
368 			//------ delete the camp as it no longer has any use ----//
369 
370 			bestCampPtr->ai_del_firm();
371 			return;
372 		}
373 	}
374 
375 	//------- get an overseer if there isn't any right now -----//
376 
377 	if( !overseer_recno )
378 		nationPtr->add_action(loc_x1, loc_y1, -1, -1, ACTION_AI_ASSIGN_OVERSEER, FIRM_CAMP);
379 
380 	//---- think about the no. of workers needed for this base ----//
381 
382 	int combatDiff;
383 
384 	if( overseer_recno == nationPtr->king_unit_recno )		// recruit as many soldiers as possible if the commander is the king
385 	{
386 		combatDiff = 1000;
387 	}
388 	else if( nationPtr->total_jobless_population > 20 + (100-nationPtr->pref_military_development) / 3 )		// 20 to 53
389 	{
390 		combatDiff = 1000;		// recruit as many as possible
391 	}
392 	else
393 	{
394 		int combatLevelNeeded = ai_combat_level_needed();
395 
396 		combatDiff = combatLevelNeeded - total_combat_level();
397 	}
398 
399 	if( combatDiff > 0 )
400 	{
401 		ai_recruit(combatDiff);
402 	}
403 	else
404 	{
405 		if( overseer_recno )
406 			ai_recruiting_soldier = 0;		// this firm has enough soldiers already
407 	}
408 }
409 //----------- End of function FirmCamp::think_recruit ----------//
410 
411 
412 //--------- Begin of function FirmCamp::ai_recruit ---------//
413 //
414 // <int> recruitCombatLevel - the combat level needed to be added.
415 //
416 // return: <int> 1-succeeded, 0-failed.
417 //
ai_recruit(int recruitCombatLevel)418 int FirmCamp::ai_recruit(int recruitCombatLevel)
419 {
420 	if( worker_count == MAX_WORKER || !overseer_recno )
421 		return 0;
422 
423 	int recruitCount = MAX( 1, recruitCombatLevel / 20 );
424 
425 	recruitCount = MIN( recruitCount, MAX_WORKER-worker_count );
426 
427 	//--- first try to recruit soldiers directly from a linked village ---//
428 
429 	int 	majorityRace = majority_race();
430 	int	raceId;
431 	int	loopCount=0;
432 	Town* townPtr;
433 
434 	for( int i=0 ; i<linked_town_count ; i++ )
435 	{
436 		townPtr = town_array[ linked_town_array[i] ];
437 
438 		if( townPtr->nation_recno != nation_recno || !townPtr->jobless_population )
439 			continue;
440 
441 		//-- recruit majority race first, but will also consider other races --//
442 
443 		raceId = MAX( 1, majorityRace );
444 
445 		for( int j=0 ; j<MAX_RACE ; j++ )
446 		{
447 			if( ++raceId > MAX_RACE )
448 				raceId = 1;
449 
450 			//--- if the loyalty is too low, reward before recruiting ---//
451 
452 			if( townPtr->jobless_race_pop_array[raceId-1] > 0 &&
453 				 townPtr->race_loyalty_array[raceId-1] < 40 )
454 			{
455 				if( townPtr->accumulated_reward_penalty > 30 )		// if the reward penalty is too high, do reward
456 					break;
457 
458 				townPtr->reward(COMMAND_AI);
459 			}
460 
461 			//---- recruit the soldiers we needed ----//
462 
463 			while( townPtr->can_recruit(raceId) )
464 			{
465 				err_when( ++loopCount > 1000 );
466 
467 				pull_town_people(townPtr->town_recno, COMMAND_AI, raceId, 1);			// last 1-force pulling people from the town to the firm
468 
469 				if( --recruitCount == 0 )
470 					return 1;
471 			}
472 		}
473 	}
474 
475 	//------ next, try to recruit from remote villages -----//
476 
477 	if( recruitCount > 0 )
478 		nation_array[nation_recno]->add_action(loc_x1, loc_y1, -1, -1, ACTION_AI_ASSIGN_WORKER, FIRM_CAMP, recruitCount);
479 
480 	return 1;
481 }
482 //----------- End of function FirmCamp::ai_recruit ----------//
483 
484 
485 //--------- Begin of function FirmCamp::ai_combat_level_needed ---------//
486 //
487 // Think about the no. of soldiers needed by this base.
488 //
ai_combat_level_needed()489 int FirmCamp::ai_combat_level_needed()
490 {
491 	Town*	  townPtr;
492 	int  	  combatNeeded=0;
493 	Nation* nationPtr = nation_array[nation_recno];
494 
495 	//------- scan for linked towns ---------//
496 
497 	for( int i=0 ; i<linked_town_count ; i++ )
498 	{
499 		townPtr = town_array[ linked_town_array[i] ];
500 
501 		//------- this is its own town -------//
502 
503 		if( townPtr->nation_recno == nation_recno )
504 		{
505 			if( townPtr->should_ai_migrate() ) 	// no need for this if this town is going to migrate
506 				continue;
507 
508 			combatNeeded += townPtr->population * 10;	// 30 people need 300 combat levels
509 
510 			if( townPtr->is_base_town )
511 				combatNeeded += townPtr->population * 10;		// double the combat level need for base town
512 		}
513 	}
514 
515 	//--- if the overseer is the king, increase its combat level needed ---//
516 
517 	if( overseer_recno && unit_array[overseer_recno]->rank_id == RANK_KING )
518 		combatNeeded = MAX(400, combatNeeded);
519 
520 	//---------------------------------------//
521 
522 	return combatNeeded;
523 }
524 //----------- End of function FirmCamp::ai_combat_level_needed ----------//
525 
526 
527 //--------- Begin of function FirmCamp::total_combat_level ---------//
528 //
529 // Total combat level of all soldiers and commander in the base.
530 // The leadership of the general also applies to the final combat level.
531 //
532 // return: <int> the total combat level - it is the sum of hit points
533 //					  of all the units in the camp.
534 //
total_combat_level()535 int FirmCamp::total_combat_level()
536 {
537 	int 	  totalCombatLevel=0;
538 	Worker* workerPtr = worker_array;
539 
540 	for( int i=0 ; i<worker_count ; i++, workerPtr++ )
541 	{
542 		totalCombatLevel += workerPtr->hit_points;			// use it points instead of combat level because hit_points represent both combat level and hit points left
543 
544 		err_when( totalCombatLevel < 0 );
545 
546 		//---- the combat level of weapons are higher ------//
547 
548 		UnitInfo* unitInfo = unit_res[workerPtr->unit_id];
549 
550 		if( unitInfo->unit_class == UNIT_CLASS_WEAPON )
551 			totalCombatLevel += (unitInfo->weapon_power + workerPtr->extra_para - 1) * 30;		// extra_para keeps the weapon version
552 
553 		err_when( totalCombatLevel < 0 );
554 	}
555 
556 	if( overseer_recno )
557 	{
558 		Unit* unitPtr = unit_array[overseer_recno];
559 
560 		//--- the commander's leadership effects over the soldiers ---//
561 
562 		totalCombatLevel += totalCombatLevel * unitPtr->skill.skill_level / 150;		// divided by 150 instead of 100 because while the attacking ability of the unit is affected by the general, the hit points isn't, so we shouldn't do a direct multiplication.
563 
564 		//------ the leader's own hit points ------//
565 
566 		totalCombatLevel += (int) unitPtr->hit_points;
567 
568 		err_when( totalCombatLevel < 0 );
569 	}
570 
571 	return totalCombatLevel;
572 }
573 //----------- End of function FirmCamp::total_combat_level ----------//
574 
575 
576 //--------- Begin of function FirmCamp::average_combat_level ---------//
577 //
average_combat_level()578 int FirmCamp::average_combat_level()
579 {
580 	int personCount = worker_count + (overseer_recno>0);
581 
582 	if( personCount > 0 )
583 		return total_combat_level() / personCount;
584 	else
585 		return 0;
586 }
587 //----------- End of function FirmCamp::average_combat_level ----------//
588 
589 
590 //--------- Begin of function FirmCamp::ai_should_close ---------//
591 //
592 // Whether this AI firm should be closed or not.
593 //
ai_should_close()594 int FirmCamp::ai_should_close()
595 {
596 	return linked_town_count==0 && linked_firm_count==0;
597 }
598 //----------- End of function FirmCamp::ai_should_close ----------//
599 
600 
601 //--------- Begin of function FirmCamp::think_capture ---------//
602 //
603 // Think about capturing towns.
604 //
think_capture()605 void FirmCamp::think_capture()
606 {
607 	if( is_attack_camp )		// if this camp has been assigned to an attack mission already
608 		return;
609 
610 	int targetTownRecno = think_capture_target_town();
611 
612 	if( !targetTownRecno )
613 		return;
614 
615 	//----- if the target town is a nation town -----//
616 
617 	Town* targetTown = town_array[targetTownRecno];
618 	Nation* ownNation = nation_array[nation_recno];
619 
620 	if( targetTown->nation_recno )
621 	{
622 		//--- if there are any defenses (camps and mobile units) on the target town, destroy them all first -----//
623 
624 		if( ownNation->attack_enemy_town_defense(targetTown) != -1 )		// only proceed further when the result is -1, which means no defense on the target town, no attacking is needed.
625 			return;
626 	}
627 
628 	//------ check if the town people will go out to defend -----//
629 
630 	float thisResistance, resistanceDiff;
631 	int   defenseCombatLevel=0;
632 
633 	for( int i=0 ; i<MAX_RACE ; i++ )
634 	{
635 		if( targetTown->race_pop_array[i] < 5 )		// if the pop count is lower than 5, ingore it
636 			continue;
637 
638 		if( targetTown->nation_recno )
639 		{
640 			thisResistance = targetTown->race_loyalty_array[i];
641 			resistanceDiff = thisResistance - MIN_NATION_DEFEND_LOYALTY;
642 		}
643 		else
644 		{
645 			thisResistance = targetTown->race_resistance_array[i][nation_recno-1];
646 			resistanceDiff = thisResistance - MIN_INDEPENDENT_DEFEND_LOYALTY;
647 		}
648 
649 		if( resistanceDiff >= 0 )
650 		{
651 			float resistanceDecPerDefender = thisResistance/targetTown->race_pop_array[i];  // resistance decrease per new defender
652 
653 			int defenderCount = int(resistanceDiff / resistanceDecPerDefender)+1;		// no. of defenders will go out if you attack this town
654 
655 			defenseCombatLevel += targetTown->town_combat_level * 2 * defenderCount;	// *2 is defenseCombatLevel is actually the sum of hit points, not combat level
656 		}
657 	}
658 
659 	//--- try using spies if there are defense forces and the nation likes to use spies ---//
660 
661 	if( defenseCombatLevel > 0 ) 		// && ownNation->pref_spy >= 50 && misc.random(3)==0 )		// 1/3 chance of using spies here, otherwise only use spies when we are not strong enough to take over the village by force
662 	{
663 		if( targetTown->nation_recno==0 )		// if the camp is trying to capture an independent town, the leadership and race id. of the overseer matters.
664 		{
665 			if( think_assign_better_overseer(targetTown) )		// a better general is being assigned to this firm, wait for it
666 				return;
667 
668 			if( think_capture_use_spy(targetTown) )
669 				return;
670 
671 			if( defenseCombatLevel > 100+ownNation->pref_military_courage &&
672 				 resistanceDiff > (100-ownNation->pref_peacefulness)/5  )		// depending on the peacefulness, the nation won't attack if resistance > (0-20)
673 			{
674 				return;
675 			}
676 		}
677 		else
678 		{
679 			//--- don't attack if the target nation's military rating is higher than ours ---//
680 
681 			if( nation_array[targetTown->nation_recno]->military_rank_rating()
682 				 > ownNation->military_rank_rating() )
683 			{
684 				return;
685 			}
686 		}
687 	}
688 
689 	//------ send out troops to capture the target town now ----//
690 
691 	int rc;
692 
693 	if( targetTown->nation_recno )
694 		rc = ai_capture_enemy_town(targetTown, defenseCombatLevel);
695 	else
696 		rc = ai_capture_independent_town(targetTown, defenseCombatLevel);
697 
698 	//-- use the same approach to capture both enemy and independent towns --//
699 
700 	if( rc )
701 	{
702 		ai_capture_town_recno = targetTownRecno;
703 		defense_flag 			 = 0;			// turn off the defense flag during capturing so the general is staying in the base to influence the town
704 
705 		//--- as the current commander has been out to attack the town by ai_attack_target(), we need to assign him back to the camp for influencing the town and eventually capture it ---//
706 
707 		if( !overseer_recno && targetTown->nation_recno && patrol_unit_count>0 )
708 			unit_array[ patrol_unit_array[0] ]->assign(loc_x1, loc_y1);
709 	}
710 }
711 //----------- End of function FirmCamp::think_capture -----------//
712 
713 
714 //--------- Begin of function FirmCamp::think_capture_target_town ---------//
715 //
716 // Think about which town to capture.
717 //
718 // Return: <int> recno of the target town.
719 //
think_capture_target_town()720 int FirmCamp::think_capture_target_town()
721 {
722 	if( !linked_town_count || !overseer_recno )
723 		return 0;
724 
725 	//--- if there are any units currently being assigned to this camp ---//
726 
727 	if( nation_array[nation_recno]->is_action_exist( loc_x1, loc_y1, -1, -1, ACTION_AI_ASSIGN_WORKER, FIRM_CAMP ) )
728 		return 0;
729 
730 	//-- decide which town to attack (only when the camp is linked to more than one town ---//
731 
732 	int	curResistance, curTargetResistance, resistanceDec;
733 	int 	i, minResistance=100, bestTownRecno=0;
734 	Town* townPtr;
735 	int   prefPeacefulness = nation_array[nation_recno]->pref_peacefulness;
736 	Nation* ownNation = nation_array[nation_recno];
737 	int   overseerRaceId = unit_array[overseer_recno]->race_id;
738 
739 	for( i=0 ; i<linked_town_count ; i++ )
740 	{
741 		townPtr = town_array[ linked_town_array[i] ];
742 
743 		if( townPtr->nation_recno == nation_recno )
744 			continue;
745 
746 		//------- if it's an independent town -------//
747 
748 		if( !townPtr->nation_recno )		// only capture independent town
749 		{
750 			curResistance = townPtr->average_resistance(nation_recno);
751 			curTargetResistance = townPtr->average_target_resistance(nation_recno);
752 
753 			resistanceDec = curResistance - curTargetResistance;
754 
755 			//------- if the resistance is decreasing ---------//
756 
757 			if( resistanceDec > 0 &&
758 				 curResistance > 25-25*ownNation->pref_peacefulness/100 &&		// for nation that has a high peacefulness preference they will wait for the loyalty to fall and try not to attack the town unless necessary
759 				 townPtr->race_pop_array[overseerRaceId-1] >= 5 )		// if it's less than 5, don't count it, as that it will be easy to attack
760 			{
761 				continue;		// let it decrease until it can no longer decrease
762 			}
763 		}
764 		else	//-------- if it's a nation town ---------//
765 		{
766 			NationRelation* nationRelation = ownNation->get_relation(townPtr->nation_recno);
767 
768 			if( nationRelation->status != NATION_HOSTILE )
769 				continue;
770 
771 			curResistance = townPtr->average_loyalty();
772 		}
773 
774 		//--------------------------------------//
775 
776 		if( curResistance < minResistance )
777 		{
778 			minResistance = curResistance;
779 			bestTownRecno = townPtr->town_recno;
780 		}
781 	}
782 
783 	return bestTownRecno;
784 }
785 //--------- End of function FirmCamp::think_capture_target_town --------//
786 
787 
788 //--------- Begin of function FirmCamp::ai_capture_independent_town -------//
789 //
790 // Try to capture the given independent town.
791 //
ai_capture_independent_town(Town * targetTown,int defenseCombatLevel)792 int FirmCamp::ai_capture_independent_town(Town* targetTown, int defenseCombatLevel)
793 {
794 	//---- see if the force is strong enough to attack the town ----//
795 
796 	Nation* nationPtr = nation_array[nation_recno];
797 
798 	int curCombatLevel = total_combat_level();		// total combat level
799 
800 	int combatDiff = defenseCombatLevel * (150+nationPtr->pref_force_projection/2) / 100
801 						  - curCombatLevel;					// try to recruit soldiers based on the force projection perference
802 
803 	if( combatDiff > 0 )
804 	{
805 		if( ai_recruit(combatDiff) )    	// try to recruit new soldiers to increase the combat ability of the troop
806 			return 0;
807 	}
808 
809 	combatDiff = defenseCombatLevel * (200-nationPtr->pref_military_courage/2) / 100
810 					 - curCombatLevel;
811 
812 	//---------- attack the target town now ----------//
813 
814 	if( nation_array[nation_recno]->ai_attack_target(targetTown->loc_x1, targetTown->loc_y1, defenseCombatLevel, 0, 0, 0, firm_recno) )
815 		return 1;
816 
817 	return 0;
818 }
819 //--------- End of function FirmCamp::ai_capture_independent_town --------//
820 
821 
822 //--------- Begin of function FirmCamp::think_capture_return ---------//
823 //
824 // Think about if the capturing units should now return to their base.
825 //
think_capture_return()826 int FirmCamp::think_capture_return()
827 {
828 	//----- if the target town is destroyed ------//
829 
830 	int returnCamp=0;
831 
832 	if( town_array.is_deleted(ai_capture_town_recno) )
833 	{
834 		returnCamp = 1;
835 	}
836 	else //---- check whether the town has been captured ----//
837 	{
838 		Town* townPtr = town_array[ai_capture_town_recno];
839 
840 		if( townPtr->nation_recno == nation_recno )		// the town has been captured
841 			returnCamp = 1;
842 	}
843 
844 	//-------- if should return to the camp now ---------//
845 
846 	if( returnCamp )
847 	{
848 		Unit* unitPtr;
849 
850 		for( int i=0; i<patrol_unit_count ; i++ )
851 		{
852 			unitPtr = unit_array[ patrol_unit_array[i] ];
853 
854 			if( unitPtr->is_visible() )
855 				unitPtr->assign(loc_x1, loc_y1);
856 		}
857 
858 		ai_capture_town_recno = 0;		// turn it on again after the capturing plan is finished
859 		defense_flag = 1;
860 		return 1;
861 	}
862 
863 	return 0;
864 }
865 //----------- End of function FirmCamp::think_capture_return -----------//
866 
867 
868 //--------- Begin of function FirmCamp::think_assign_better_overseer -------//
869 //
think_assign_better_overseer(Town * targetTown)870 int FirmCamp::think_assign_better_overseer(Town* targetTown)
871 {
872 	//----- check if there is already a queued action -----//
873 
874 	Nation* ownNation = nation_array[nation_recno];
875 
876 	if( ownNation->is_action_exist( loc_x1, loc_y1, -1, -1,
877 		 ACTION_AI_ASSIGN_OVERSEER, FIRM_CAMP ) )
878 	{
879 		return 1;		// there is a queued action being processed already
880 	}
881 
882 	//------ get the two most populated races of the town ----//
883 
884 	int mostRaceId1, mostRaceId2;
885 
886 	targetTown->get_most_populated_race(mostRaceId1, mostRaceId2);
887 
888 	//-- if the resistance of the majority race has already dropped to its lowest possible --//
889 
890 	if( targetTown->race_resistance_array[mostRaceId1-1][nation_recno-1] <=
891 		 (float) (targetTown->race_target_resistance_array[mostRaceId1-1][nation_recno-1]+1) )
892 	{
893 		if( targetTown->race_resistance_array[mostRaceId1-1][nation_recno-1] > 30 )
894 		{
895 			if( think_assign_better_overseer2(targetTown->town_recno, mostRaceId1) )
896 				return 1;
897 		}
898 	}
899 
900 	//-- if the resistance of the 2nd majority race has already dropped to its lowest possible --//
901 
902 	if( targetTown->race_resistance_array[mostRaceId2-1][nation_recno-1] <=
903 		 (float) (targetTown->race_target_resistance_array[mostRaceId2-1][nation_recno-1]+1) )
904 	{
905 		if( targetTown->race_resistance_array[mostRaceId2-1][nation_recno-1] > 30 )
906 		{
907 			if( think_assign_better_overseer2(targetTown->town_recno, mostRaceId2) )
908 				return 1;
909 		}
910 	}
911 
912 	return 0;
913 }
914 //--------- End of function FirmCamp::think_assign_better_overseer --------//
915 
916 
917 //--------- Begin of function FirmCamp::think_assign_better_overseer2 -------//
918 //
think_assign_better_overseer2(int targetTownRecno,int raceId)919 int FirmCamp::think_assign_better_overseer2(int targetTownRecno, int raceId)
920 {
921 	int reduceResistance;
922 
923 	Nation* ownNation = nation_array[nation_recno];
924 
925 	int bestUnitRecno = ownNation->find_best_capturer(targetTownRecno, raceId, reduceResistance);
926 
927 	if( !bestUnitRecno || bestUnitRecno==overseer_recno )		// if we already got the best one here
928 		return 0;
929 
930 	//---- only assign new overseer if the new one's leadership is significantly higher than the current one ----//
931 
932 	if( overseer_recno &&
933 		 unit_array[bestUnitRecno]->skill.skill_level < unit_array[overseer_recno]->skill.skill_level + 15 )
934 	{
935 		return 0;
936 	}
937 
938 	//------ check what the best unit is -------//
939 
940 	if( !ownNation->mobilize_capturer(bestUnitRecno) )
941 		return 0;
942 
943 	//---------- add the action to the queue now ----------//
944 
945 	int actionRecno = ownNation->add_action( loc_x1, loc_y1, -1, -1,
946 							ACTION_AI_ASSIGN_OVERSEER, FIRM_CAMP, 1, bestUnitRecno );
947 
948 	if( actionRecno )
949 		ownNation->process_action(actionRecno);
950 
951 	return 1;
952 }
953 //--------- End of function FirmCamp::think_assign_better_overseer2 --------//
954 
955 
956 //--------- Begin of function FirmCamp::ai_capture_enemy_town -------//
957 //
958 // When capturing an enemy town, the commander should stay in the
959 // command base to influence the village and reinforcement should be
960 // sent instead of using the troop in the base for attacking the enemies.
961 //
ai_capture_enemy_town(Town * targetTown,int defenseCombatLevel)962 int FirmCamp::ai_capture_enemy_town(Town* targetTown, int defenseCombatLevel)
963 {
964 	int useAllCamp = 0;
965 
966 	Nation* ownNation = nation_array[nation_recno];
967 	Nation* targetNation = nation_array[targetTown->nation_recno];
968 
969 	int ourMilitary   = ownNation->military_rank_rating();
970 	int enemyMilitary = targetNation->military_rank_rating();
971 
972 	//--- use all camps to attack if we have money and we are stronger than the enemy ---//
973 
974 	if( ourMilitary - enemyMilitary > 30 && ownNation->ai_should_spend(ownNation->pref_military_courage/2) )
975 		useAllCamp = 1;
976 
977 	//---- use all camps to attack the enemy if the enemy is a human player
978 
979 	else if( config.ai_aggressiveness >= OPTION_MODERATE &&
980 				!targetNation->is_ai() && ourMilitary > enemyMilitary )
981 	{
982 		if( config.ai_aggressiveness >= OPTION_HIGH ||
983 			 ownNation->pref_peacefulness < 50 )
984 		{
985 			useAllCamp = 1;
986 		}
987 	}
988 
989 	return nation_array[nation_recno]->ai_attack_target(targetTown->loc_x1, targetTown->loc_y1,
990 			 defenseCombatLevel, 0, 0, 0, firm_recno, useAllCamp );
991 }
992 //--------- End of function FirmCamp::ai_capture_enemy_town --------//
993 
994 
995 //--------- Begin of function FirmCamp::think_capture_use_spy ---------//
996 //
997 // Think about using spies for capturing the target town.
998 //
think_capture_use_spy(Town * targetTown)999 int FirmCamp::think_capture_use_spy(Town* targetTown)
1000 {
1001 	Nation* ownNation = nation_array[nation_recno];
1002 
1003 	//------ get the two most populated races of the town ----//
1004 
1005 	int mostRaceId1, mostRaceId2;
1006 
1007 	targetTown->get_most_populated_race(mostRaceId1, mostRaceId2);
1008 
1009 	//-- get the current number of our spies in this town and see if we need more --//
1010 
1011 	int spyCount;
1012 	int curSpyLevel = spy_array.total_spy_skill_level( SPY_TOWN, targetTown->town_recno, nation_recno, spyCount );
1013 
1014 	//--------------------------------------------//
1015 
1016 	int rc=0;
1017 
1018 	if( think_capture_use_spy2(targetTown, mostRaceId1, curSpyLevel ) )
1019 		rc = 1;
1020 
1021 	if( mostRaceId2 )
1022 	{
1023 		if( think_capture_use_spy2(targetTown, mostRaceId2, curSpyLevel ) )
1024 			rc = 1;
1025 	}
1026 
1027 	return rc;
1028 }
1029 //----------- End of function FirmCamp::think_capture_use_spy -----------//
1030 
1031 
1032 //--------- Begin of function FirmCamp::think_capture_use_spy2 ---------//
1033 //
1034 // Think about using spies for capturing the target town.
1035 //
think_capture_use_spy2(Town * targetTown,int raceId,int curSpyLevel)1036 int FirmCamp::think_capture_use_spy2(Town* targetTown, int raceId, int curSpyLevel)
1037 {
1038 	Nation* ownNation = nation_array[nation_recno];
1039 
1040 	int curResistance, targetResistance;
1041 
1042 	if( targetTown->nation_recno )
1043 	{
1044 		curResistance 	  = (int) targetTown->race_loyalty_array[raceId-1];
1045 		targetResistance = targetTown->race_target_loyalty_array[raceId-1];
1046 	}
1047 	else
1048 	{
1049 		curResistance    = (int) targetTown->race_resistance_array[raceId-1][nation_recno-1];
1050 		targetResistance = targetTown->race_target_resistance_array[raceId-1][nation_recno-1];
1051 	}
1052 
1053 	int minResistance = MIN(curResistance, targetResistance);
1054 
1055 	//----- if the resistance is low enough, don't have to use spies -----//
1056 
1057 	if( targetTown->nation_recno )
1058 	{
1059 		if( minResistance < MIN_NATION_DEFEND_LOYALTY )
1060 			return 0;
1061 	}
1062 	else
1063 	{
1064 		if( minResistance < MIN_INDEPENDENT_DEFEND_LOYALTY )
1065 			return 0;
1066 	}
1067 
1068 	//----- if the needed spy level > current spy level, assign more spies ----//
1069 
1070 	int neededSpyLevel = minResistance * (50+ownNation->pref_spy) / 50;
1071 
1072 	if( neededSpyLevel > curSpyLevel )
1073 		return ownNation->ai_assign_spy_to_town(targetTown->town_recno, raceId);
1074 
1075 	return 0;
1076 }
1077 //----------- End of function FirmCamp::think_capture_use_spy2 -----------//
1078 
1079 
1080 //--------- Begin of function FirmCamp::ai_update_link_status ---------//
1081 //
1082 // Updating link status of this firm with towns.
1083 //
1084 // It's a overloaded function of Firm::ai_update_link_status().
1085 //
ai_update_link_status()1086 void FirmCamp::ai_update_link_status()
1087 {
1088 	Nation* ownNation = nation_array[nation_recno];
1089 
1090 	//------ always enable links to all towns -----//
1091 
1092 	for( int i=0 ; i<linked_town_count ; i++ )
1093 	{
1094 		Town* townPtr = town_array[linked_town_array[i]];
1095 
1096 		//---- don't try to capture other nation's towns unless the AI is at war or tense with the nation ----//
1097 
1098 		if( townPtr->nation_recno &&
1099 			 ownNation->get_relation_status(townPtr->nation_recno) <= NATION_TENSE )		// hostile or tense
1100 		{
1101 			continue;
1102 		}
1103 
1104 		toggle_town_link( i+1, 1, COMMAND_AI );
1105 
1106 		//------------------------------------------------------------------//
1107 		// Here we only update this camp's link to the town.
1108 		// The town's link to this firm is updated in Town::update_target_loyalty().
1109 		//------------------------------------------------------------------//
1110 	}
1111 }
1112 //----------- End of function FirmCamp::ai_update_link_status ----------//
1113 
1114 
1115 //------- Begin of function FirmCamp::ai_has_excess_worker -------//
1116 //
1117 // Return whether this firm has any excessive soldiers or not.
1118 //
ai_has_excess_worker()1119 int FirmCamp::ai_has_excess_worker()
1120 {
1121 	if( linked_town_count==0 )
1122 		return 1;
1123 
1124 	if( ai_capture_town_recno )		// no if the camp is trying to capture an independent town
1125 		return 0;
1126 
1127 	if( is_attack_camp )		// no if the camp is trying to capture an independent town
1128 		return 0;
1129 
1130 	if( should_close_flag )
1131 		return 1;
1132 
1133 	return 0;
1134 
1135 //	return total_combat_level() > ai_combat_level_needed()+100;
1136 }
1137 //--------- End of function FirmCamp::ai_has_excess_worker -------//
1138 
1139 
1140 //------- Begin of function FirmCamp::think_use_cash_to_capture -------//
1141 //
1142 // Think about using money to decrease the resistance of the
1143 // independent villagers.
1144 //
think_use_cash_to_capture()1145 int FirmCamp::think_use_cash_to_capture()
1146 {
1147 	if( !nation_array[nation_recno]->should_use_cash_to_capture() )
1148 		return 0;
1149 
1150 	//-------------------------------------//
1151 
1152 	Town* townPtr;
1153 
1154 	for( int i=0 ; i<linked_town_count ; i++ )
1155 	{
1156 		townPtr = town_array[ linked_town_array[i] ];
1157 
1158 		if( townPtr->nation_recno == nation_recno )
1159 			continue;
1160 
1161 		if( townPtr->accumulated_enemy_grant_penalty > 0 )
1162 			continue;
1163 
1164 		if( townPtr->can_grant_to_non_own_town(nation_recno) )
1165 			townPtr->grant_to_non_own_town(nation_recno, COMMAND_AI);
1166 	}
1167 
1168 	return 1;
1169 }
1170 //--------- End of function FirmCamp::think_use_cash_to_capture -------//
1171 
1172 
1173 //------- Begin of function FirmCamp::think_linked_town_change_nation ------//
1174 //
1175 // This function is called by Town::set_nation() when a town linked
1176 // to this firm has changed nation.
1177 //
1178 // <int> linkedTownRecno - the recno of the town that has changed nation.
1179 // <int> oldNationRecno  - the old nation recno of the town
1180 // <int> newNationRecno  - the new nation recno of the town
1181 //
think_linked_town_change_nation(int linkedTownRecno,int oldNationRecno,int newNationRecno)1182 void FirmCamp::think_linked_town_change_nation(int linkedTownRecno, int oldNationRecno, int newNationRecno)
1183 {
1184 	//-----------------------------------------------//
1185 	//
1186 	// If we are trying to capture an independent town and our
1187 	// enemies have managed to capture it first.
1188 	//
1189 	//-----------------------------------------------//
1190 
1191 	Nation* ownNation = nation_array[nation_recno];
1192 
1193 	if( oldNationRecno==0 && newNationRecno>0 && newNationRecno != nation_recno  )
1194 	{
1195 		Town* townPtr = town_array[linkedTownRecno];
1196 
1197 		//--- if the town does not have any protection, then don't remove this camp ---//
1198 
1199 		if( townPtr->protection_available()==0 )
1200 			return;
1201 
1202 		should_close_flag = 1;
1203 		ownNation->firm_should_close_array[firm_id-1]++;
1204 	}
1205 }
1206 //-------- End of function FirmCamp::think_linked_town_change_nation ------//
1207 
1208 
1209 //------- Begin of function FirmCamp::think_attack_nearby_enemy -------//
1210 //
1211 // Think about attacking enemies near this cmap.
1212 //
think_attack_nearby_enemy()1213 int FirmCamp::think_attack_nearby_enemy()
1214 {
1215 	//------------------------------------------//
1216 
1217 	Nation* 	nationPtr = nation_array[nation_recno];
1218 
1219 	int scanRange = 6 + nationPtr->pref_military_courage/20;		// 6 to 11
1220 
1221 	int xLoc1 = loc_x1 - scanRange;
1222 	int yLoc1 = loc_y1 - scanRange;
1223 	int xLoc2 = loc_x2 + scanRange;
1224 	int yLoc2 = loc_y2 + scanRange;
1225 
1226 	xLoc1 = MAX( xLoc1, 0 );
1227 	yLoc1 = MAX( yLoc1, 0 );
1228 	xLoc2 = MIN( xLoc2, MAX_WORLD_X_LOC-1 );
1229 	yLoc2 = MIN( yLoc2, MAX_WORLD_Y_LOC-1 );
1230 
1231 	//------------------------------------------//
1232 
1233 	int		enemyCombatLevel=0;		// the higher the rating, the easier we can attack the target town.
1234 	int 		xLoc, yLoc;
1235 	int		enemyXLoc= -1, enemyYLoc;
1236 	Unit* 	unitPtr;
1237 	Location* locPtr;
1238 
1239 	for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
1240 	{
1241 		locPtr = world.get_loc(xLoc1, yLoc);
1242 
1243 		for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ )
1244 		{
1245 			//--- if there is an enemy unit here ---//
1246 
1247 			if( locPtr->has_unit(UNIT_LAND) )
1248 			{
1249 				unitPtr = unit_array[ locPtr->unit_recno(UNIT_LAND) ];
1250 
1251 				if( !unitPtr->nation_recno )
1252 					continue;
1253 
1254 				//--- if the unit is idle and he is our enemy ---//
1255 
1256 				if( unitPtr->cur_action == SPRITE_ATTACK &&
1257 					 nationPtr->get_relation_status(unitPtr->nation_recno) == NATION_HOSTILE )
1258 				{
1259 					err_when( unitPtr->nation_recno == nation_recno );
1260 
1261 					enemyCombatLevel += (int) unitPtr->hit_points;
1262 
1263 					if( enemyXLoc == -1 || misc.random(5)==0 )
1264 					{
1265 						enemyXLoc = xLoc;
1266 						enemyYLoc = yLoc;
1267 					}
1268 				}
1269 			}
1270 		}
1271 	}
1272 
1273 	if( enemyCombatLevel==0 )
1274 		return 0;
1275 
1276 	err_when( enemyXLoc < 0 );
1277 
1278 	//--------- attack the target now -----------//
1279 
1280 	if( worker_count > 0 )
1281 	{
1282 		patrol_all_soldier();
1283 
1284 		if( patrol_unit_count > 0 )
1285 		{
1286 			// ###### patch begin Gilbert 5/8 ########//
1287 			unit_array.attack(enemyXLoc, enemyYLoc, 0, patrol_unit_array, patrol_unit_count, COMMAND_AI,
1288 				world.get_loc(enemyXLoc, enemyYLoc)->unit_recno(UNIT_LAND));
1289 			// ###### patch end Gilbert 5/8 ########//
1290 			return 1;
1291 		}
1292 	}
1293 
1294 	return 0;
1295 }
1296 //-------- End of function FirmCamp::think_attack_nearby_enemy -------//
1297 
1298 
1299 //------- Begin of function FirmCamp::think_change_town_link -------//
1300 //
1301 // Think about changing links to foreign towns.
1302 //
think_change_town_link()1303 void FirmCamp::think_change_town_link()
1304 {
1305 	Nation* ownNation = nation_array[nation_recno];
1306 
1307 	for( int i=linked_town_count-1 ; i>=0 ; i-- )
1308 	{
1309 		Town* townPtr = town_array[ linked_town_array[i] ];
1310 
1311 		//--- only change links to foreign towns, links to own towns are always on ---//
1312 
1313 		if( townPtr->nation_recno == nation_recno )
1314 			continue;
1315 
1316 		//---- only enable links to non-friendly towns ----//
1317 
1318 		int enableFlag = townPtr->nation_recno==0 ||
1319 							  ownNation->get_relation(townPtr->nation_recno)->status == NATION_HOSTILE;
1320 
1321 		toggle_town_link( i+1, enableFlag, COMMAND_AI );
1322 	}
1323 }
1324 //--------- End of function FirmCamp::think_change_town_link -------//
1325 
1326 
1327 //------- Begin of function FirmCamp::think_assign_better_commander -------//
1328 //
1329 // Assign a better commander to this camp.
1330 //
think_assign_better_commander()1331 int FirmCamp::think_assign_better_commander()
1332 {
1333 	//----- if there is already an overseer being assigned to the camp ---//
1334 
1335 	Nation* ownNation = nation_array[nation_recno];
1336 
1337 	int actionRecno = ownNation->is_action_exist(loc_x1, loc_y1, -1, -1,
1338 							 ACTION_AI_ASSIGN_OVERSEER, FIRM_CAMP);
1339 
1340 	//--- if there is already one existing ---//
1341 
1342 	if( actionRecno )
1343 	{
1344 		//--- if the action still is already being processed, don't bother with it ---//
1345 
1346 		if( ownNation->get_action(actionRecno)->processing_instance_count > 0 )
1347 			return 0;
1348 
1349 		//--- however, if the action hasn't been processed, we still try to use the approach here ---//
1350 	}
1351 
1352 	//-------------------------------------------------//
1353 
1354 	Firm*   firmPtr;
1355 	Worker* workerPtr;
1356 	int     bestRaceId = best_commander_race();
1357 	int	  bestFirmRecno=0, bestWorkerId;
1358 	int  	  bestLeadership=0;
1359 
1360 	if( overseer_recno )
1361 	{
1362 		bestLeadership	= cur_commander_leadership(bestRaceId)
1363 							  + 10 + ownNation->pref_loyalty_concern/10;			// nations that have higher loyalty concern will not switch commander too frequently
1364 	}
1365 
1366 	//--- locate for a soldier who has a higher leadership ---//
1367 
1368 	for( int i=ownNation->ai_camp_count-1 ; i>=0 ; i-- )
1369 	{
1370 		firmPtr = firm_array[ ownNation->ai_camp_array[i] ];
1371 
1372 		if( firmPtr->region_id != region_id )
1373 			continue;
1374 
1375 		workerPtr = firmPtr->worker_array;
1376 
1377 		for( int j=1 ; j<=firmPtr->worker_count ; j++, workerPtr++ )
1378 		{
1379 			if( !workerPtr->race_id )
1380 				continue;
1381 
1382 			int workerLeadership = workerPtr->skill_level;
1383 
1384 			if( workerPtr->race_id != bestRaceId )
1385 				workerLeadership /= 2;
1386 
1387 			if( workerLeadership > bestLeadership )
1388 			{
1389 				bestLeadership = workerLeadership;
1390 				bestFirmRecno  = firmPtr->firm_recno;
1391 				bestWorkerId   = j;
1392 			}
1393 		}
1394 	}
1395 
1396 	if( bestFirmRecno == 0 )
1397 		return 0;
1398 
1399 	//-------- assign the overseer now -------//
1400 
1401 	int unitRecno = firm_array[bestFirmRecno]->mobilize_worker(bestWorkerId, COMMAND_AI);
1402 
1403 	if( !unitRecno )
1404 		return 0;
1405 
1406 	Unit* unitPtr = unit_array[unitRecno];
1407 
1408 	unitPtr->set_rank(RANK_GENERAL);
1409 
1410 	//---- if there is already an existing but unprocessed one, delete it first ---//
1411 
1412 	if( actionRecno )
1413 		ownNation->del_action(actionRecno);
1414 
1415 	return ownNation->add_action(loc_x1, loc_y1, -1, -1, ACTION_AI_ASSIGN_OVERSEER, FIRM_CAMP, 1, unitRecno);
1416 }
1417 //-------- End of function FirmCamp::think_assign_better_commander ---------//
1418 
1419 
1420 //------- Begin of function FirmCamp::cur_commander_leadership -------//
1421 //
1422 // [int] bestRaceId - if this is given, it will be used, otherwise
1423 //							 it will use best_commander_race().
1424 //
1425 // Return the commander leadership
1426 //
cur_commander_leadership(int bestRaceId)1427 int FirmCamp::cur_commander_leadership(int bestRaceId)
1428 {
1429 	int commanderLeadership=0;
1430 
1431 	//--- get the current leadership of the commander ----//
1432 
1433 	if( overseer_recno )
1434 	{
1435 		if( !bestRaceId )
1436 			bestRaceId = best_commander_race();
1437 
1438 		Unit* unitCommander = unit_array[overseer_recno];
1439 
1440 		if( unitCommander->race_id == bestRaceId )
1441 			commanderLeadership = unitCommander->skill.skill_level;
1442 		else
1443 			commanderLeadership = unitCommander->skill.skill_level / 2;		// divided by 2 if the race doesn't match
1444 	}
1445 
1446 	return commanderLeadership;
1447 }
1448 //-------- End of function FirmCamp::cur_commander_leadership ---------//
1449 
1450 
1451 //------- Begin of function FirmCamp::new_commander_leadership -------//
1452 //
1453 // <int> newRaceId 	  - the race id. of the would-be commander.
1454 // <int> newSkillLevel - the skill level of the would-be commander.
1455 //
1456 // Return the commander leadership if the unit is assigned to this camp.
1457 //
new_commander_leadership(int newRaceId,int newSkillLevel)1458 int FirmCamp::new_commander_leadership(int newRaceId, int newSkillLevel)
1459 {
1460 	int commanderLeadership=0;
1461 	int bestRaceId = best_commander_race();
1462 
1463 	//--- get the current leadership of the commander ----//
1464 
1465 	if( overseer_recno )
1466 	{
1467 		if( newRaceId == bestRaceId )
1468 			commanderLeadership = newSkillLevel;
1469 		else
1470 			commanderLeadership = newSkillLevel / 2;		// divided by 2 if the race doesn't match
1471 	}
1472 
1473 	return commanderLeadership;
1474 }
1475 //-------- End of function FirmCamp::new_commander_leadership ---------//
1476 
1477 
1478 //------- Begin of function FirmCamp::best_commander_race -------//
1479 //
1480 // Return what race the commander should be for this camp.
1481 //
best_commander_race()1482 int FirmCamp::best_commander_race()
1483 {
1484 	//---------------------------------------------//
1485 	//
1486 	// If this camp is the commanding camp of a town,
1487 	// then return the majority race of the town.
1488 	//
1489 	// A camp is the commanding camp of a town when
1490 	// it is the closest camp to the town.
1491 	//
1492 	//---------------------------------------------//
1493 
1494 	for( int i=linked_town_count-1 ; i>=0 ; i-- )
1495 	{
1496 		Town* townPtr = town_array[ linked_town_array[i] ];
1497 
1498 		if( townPtr->closest_own_camp() == firm_recno )
1499 			return townPtr->majority_race();
1500 	}
1501 
1502 	//----- check if this camp is trying to capture an independent town ---//
1503 
1504 	int targetTownRecno = think_capture_target_town();
1505 
1506 	if( targetTownRecno && town_array[targetTownRecno]->nation_recno==0 )
1507 		return town_array[targetTownRecno]->majority_race();
1508 
1509 	//----- Otherwise return the majority race of this camp -----//
1510 
1511 	return majority_race();
1512 }
1513 //-------- End of function FirmCamp::best_commander_race ---------//
1514 
1515