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