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    : OUNITAI.CPP
22 //Description : Object Unit AI
23 
24 #include <OSYS.h>
25 #include <OSPY.h>
26 #include <OREBEL.h>
27 #include <OUNIT.h>
28 #include <OCONFIG.h>
29 #include <OREGIONS.h>
30 #include <OF_CAMP.h>
31 #include <ONATION.h>
32 
33 #ifdef NO_DEBUG_UNIT
34 #undef err_when
35 #undef err_here
36 #undef err_if
37 #undef err_else
38 #undef err_now
39 #define err_when(cond)
40 #define err_here()
41 #define err_if(cond)
42 #define err_else
43 #define err_now(msg)
44 #undef DEBUG
45 #endif
46 
47 //--------- Begin of function Unit::process_ai --------//
48 //
49 // [int] forceExecute - whether force execute all AI functions
50 //								without checking day interavals.
51 //							   (default: 0)
52 //
process_ai()53 void Unit::process_ai()
54 {
55 	err_when( !nation_recno );
56 
57 	//-*********** simulate aat ************-//
58 	#ifdef DEBUG
59 		if(debug_sim_game_type)
60 			return;
61 	#endif
62 	//-*********** simulate aat ************-//
63 
64 	//------ the aggressive_mode of AI units is always 1 ------//
65 
66 	aggressive_mode = 1;
67 
68 	//------- handle Seek Path failures ------//
69 
70 	if( ai_handle_seek_path_fail() )
71 		return;
72 
73 	//--- if it's a spy from other nation, don't control it ---//
74 
75 	if( spy_recno && true_nation_recno() != nation_recno )
76 	{
77 		//--- a random chance of the AI catching the spy and resign it ---//
78 
79 		if( is_visible() && misc.random(365 * FRAMES_PER_DAY)==0 )		// if the unit stay outside for one year, it will get caught
80 		{
81 			stop2();
82 			resign(COMMAND_AI);
83 			return;
84 		}
85 
86 		if( !spy_array[spy_recno]->notify_cloaked_nation_flag )		// if notify_cloaked_nation_flag is 1, the nation will take it as its own spies
87 			return;
88 	}
89 
90 	//----- think about rewarding this unit -----//
91 
92 	if( race_id && rank_id != RANK_KING &&
93 		 info.game_date%5 == sprite_recno%5 )
94 	{
95 		think_reward();
96 	}
97 
98 	//-----------------------------------------//
99 
100 	if( !is_visible() )
101 		return;
102 
103 	//--- if the unit has stopped, but ai_action_id hasn't been reset ---//
104 
105 	if( cur_action==SPRITE_IDLE && action_mode==ACTION_STOP &&
106 		 action_mode2==ACTION_STOP && ai_action_id )
107 	{
108 		nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
109 
110 		err_when( ai_action_id );		// it should have been reset
111 	}
112 
113 	//---- King flees under attack or surrounded by enemy ---//
114 
115 	if( race_id && rank_id==RANK_KING )
116 	{
117 		if( think_king_flee() )
118 			return;
119 	}
120 
121 	//---- General flees under attack or surrounded by enemy ---//
122 
123 	if( race_id && rank_id==RANK_GENERAL &&
124 		 info.game_date%7 == sprite_recno%7 )
125 	{
126 		if( think_general_flee() )
127 			return;
128 	}
129 
130 	//-- let Unit::next_day() process it process original_action_mode --//
131 
132 	if( original_action_mode )
133 		return;
134 
135 	//------ if the unit is not stop right now ------//
136 
137 	if( !is_ai_all_stop() )
138 	{
139 		think_stop_chase();
140 		return;
141 	}
142 
143 	//-----------------------------------------//
144 
145 	if( mobile_type==UNIT_LAND )
146 	{
147 		if( ai_escape_fire() )
148 			return;
149 	}
150 
151 	//---------- if this is your spy --------//
152 
153 	if( spy_recno && true_nation_recno()==nation_recno )
154 		think_spy_action();
155 
156 	//------ if this unit is from a camp --------//
157 
158 	if( home_camp_firm_recno )
159 	{
160 		Firm* firmCamp = firm_array[home_camp_firm_recno];
161 		int   rc;
162 
163 		if( rank_id == RANK_SOLDIER )
164 			rc = firmCamp->worker_count < MAX_WORKER;
165 		else
166 			rc = !firmCamp->overseer_recno;
167 
168 		if( rc )
169 		{
170 			if( return_camp() )
171 				return;
172 		}
173 
174 		home_camp_firm_recno = 0;		// the camp is already occupied by somebody
175 	}
176 
177 	//----------------------------------------//
178 
179 	if( race_id && rank_id==RANK_KING )
180 	{
181 		think_king_action();
182 	}
183 	else if( race_id && rank_id==RANK_GENERAL )
184 	{
185 		think_general_action();
186 	}
187 	else
188 	{
189 		if( unit_res[unit_id]->unit_class == UNIT_CLASS_WEAPON )
190 		{
191 			if( info.game_date%15 == sprite_recno%15 )	// don't call too often as the action may fail and it takes a while to call the function each time
192 			{
193 				think_weapon_action();	//-- ships AI are called in UnitMarine --//
194 			}
195 		}
196 		else if( race_id )
197 		{
198 			//--- if previous attempts for new action failed, don't call think_normal_human_action() so frequently then ---//
199 
200 			if( ai_no_suitable_action )
201 			{
202 				if( info.game_date%15 != sprite_recno%15 )	// don't call too often as the action may fail and it takes a while to call the function each time
203 					return;
204 			}
205 
206 			//---------------------------------//
207 
208 			if( !think_normal_human_action() )
209 			{
210 				ai_no_suitable_action = 1; 	// set this flag so think_normal_human_action() won't be called continously
211 
212 				if( !leader_unit_recno )		// only when the unit is not led by a commander
213 				{
214 					resign(COMMAND_AI);
215 				}
216 				else
217 				{
218 					ai_move_to_nearby_town();
219 				}
220 			}
221 		}
222 	}
223 }
224 //---------- End of function Unit::process_ai --------//
225 
226 
227 //--------- Begin of function Unit::think_stop_chase --------//
228 
think_stop_chase()229 int Unit::think_stop_chase()
230 {
231 	//-----------------------------------------------------//
232 	//
233 	// Stop the chase if the target is being far away from
234 	// its original attacking location.
235 	//
236 	//-----------------------------------------------------//
237 
238 	if( !(action_mode==ACTION_ATTACK_UNIT && ai_original_target_x_loc>=0) )
239 		return 0;
240 
241 	if( unit_array.is_deleted(action_para) )
242 	{
243 		stop2();
244 		return 1;
245 	}
246 
247 	Unit* targetUnit = unit_array[action_para];
248 
249 	if( !targetUnit->is_visible() )
250 	{
251 		stop2();
252 		return 1;
253 	}
254 
255 	//----------------------------------------//
256 
257 	int aiChaseDistance = 10 + nation_array[nation_recno]->pref_military_courage/20;		// chase distance: 10 to 15
258 
259 	int curDistance = misc.points_distance( targetUnit->next_x_loc(), targetUnit->next_y_loc(),
260 							ai_original_target_x_loc, ai_original_target_y_loc );
261 
262 	if( curDistance <= aiChaseDistance )
263 		return 0;
264 
265 	//--------- stop the unit ----------------//
266 
267 	stop2();
268 
269 	//--- if this unit leads a troop, stop the action of all troop members as well ---//
270 
271 	int leaderUnitRecno;
272 
273 	if( leader_unit_recno )
274 		leaderUnitRecno = leader_unit_recno;
275 	else
276 		leaderUnitRecno = sprite_recno;
277 
278 	TeamInfo* teamInfo = unit_array[leaderUnitRecno]->team_info;
279 
280 	if( teamInfo )
281 	{
282 		for( int i=teamInfo->member_count-1 ; i>=0 ; i-- )
283 		{
284 			int unitRecno = teamInfo->member_unit_array[i];
285 
286 			if( unit_array.is_deleted(unitRecno) )
287 				continue;
288 
289 			unit_array[unitRecno]->stop2();
290 		}
291 	}
292 
293 	return 1;
294 }
295 //---------- End of function Unit::think_stop_chase --------//
296 
297 
298 //--------- Begin of function Unit::is_ai_all_stop --------//
299 
is_ai_all_stop()300 int Unit::is_ai_all_stop()
301 {
302 	return cur_action==SPRITE_IDLE && action_mode==ACTION_STOP &&
303 			 action_mode2==ACTION_STOP && !ai_action_id;
304 }
305 //---------- End of function Unit::is_ai_all_stop --------//
306 
307 
308 //--------- Begin of function Unit::ai_move_to_nearby_town --------//
309 
ai_move_to_nearby_town()310 void Unit::ai_move_to_nearby_town()
311 {
312 	//---- look for towns to assign to -----//
313 
314 	Nation* ownNation = nation_array[nation_recno];
315 	Town *townPtr, *bestTown=NULL;
316 	int  regionId = world.get_region_id( next_x_loc(), next_y_loc() );
317 	int  curDistance, curRating, bestRating=0;
318 	int  curXLoc = next_x_loc(), curYLoc = next_y_loc();
319 
320 	for( int i=town_array.size() ; i>0 ; i-- )		// can't use ai_town_array[] because this function will be called by Unit::betray() when a unit defected to the player's kingdom
321 	{
322 		if( town_array.is_deleted(i) )
323 			continue;
324 
325 		townPtr = town_array[i];
326 
327 		if( townPtr->nation_recno != nation_recno )
328 			continue;
329 
330 		if( townPtr->region_id != regionId )
331 			continue;
332 
333 		//-------------------------------------//
334 
335 		curDistance = misc.points_distance(curXLoc, curYLoc, townPtr->center_x, townPtr->center_y );
336 
337 		if( curDistance < 10 )		// no need to move if the unit is already close enough to the town.
338 			return;
339 
340 		curRating = 100 - 100 * curDistance / MAX_WORLD_X_LOC;
341 
342 		curRating += townPtr->population;
343 
344 		//-------------------------------------//
345 
346 		if( curRating > bestRating )
347 		{
348 			bestRating = curRating;
349 			bestTown   = townPtr;
350 		}
351 	}
352 
353 	if( bestTown )
354 		move_to_town_surround(bestTown->loc_x1, bestTown->loc_y1, sprite_info->loc_width, sprite_info->loc_height);
355 }
356 //---------- End of function Unit::ai_move_to_nearby_town --------//
357 
358 
359 //--------- Begin of function Unit::ai_escape_fire --------//
360 //
361 // Move away if the unit currently stands on a burning ground.
362 //
ai_escape_fire()363 int Unit::ai_escape_fire()
364 {
365 	if(cur_action!=SPRITE_IDLE)
366 		return 0;
367 
368 	if(mobile_type!=UNIT_LAND)
369 		return 0;
370 
371 	Location *locPtr = world.get_loc(next_x_loc(), next_y_loc());
372 
373 	if( !locPtr->fire_str() )
374 		return 0;
375 
376 	//--------------------------------------------//
377 
378 	int checkLimit = 400; // checking for 400 location
379 	int xShift, yShift, checkXLoc, checkYLoc;
380 	int curXLoc = next_x_loc();
381 	int curYLoc = next_y_loc();
382 
383 	for(int i=2; i<checkLimit; i++)
384 	{
385 		misc.cal_move_around_a_point(i, 20, 20, xShift, yShift);
386 
387 		checkXLoc = curXLoc + xShift;
388 		checkYLoc = curYLoc + yShift;
389 
390 		if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
391 			continue;
392 
393 		if(!locPtr->can_move(mobile_type))
394 			continue;
395 
396 		locPtr = world.get_loc(checkXLoc, checkYLoc);
397 
398 		if( locPtr->fire_str()==0 )		// move to a safe place now
399 		{
400 			move_to(checkXLoc, checkYLoc);
401 			return 1;
402 		}
403 	}
404 
405 	return 0;
406 }
407 //---------- End of function Unit::ai_escape_fire --------//
408 
409 
410 //--------- Begin of function Unit::think_spy_action --------//
411 
think_spy_action()412 void Unit::think_spy_action()
413 {
414 	ai_move_to_nearby_town();		// just move it to one of our towns
415 }
416 //---------- End of function Unit::think_spy_action --------//
417 
418 
419 //--------- Begin of function Unit::think_king_action --------//
420 
think_king_action()421 int Unit::think_king_action()
422 {
423 	return think_leader_action();
424 }
425 //---------- End of function Unit::think_king_action --------//
426 
427 
428 //--------- Begin of function Unit::think_general_action --------//
429 
think_general_action()430 int Unit::think_general_action()
431 {
432 	if( think_leader_action() )
433 		return 1;
434 
435 	//--- if the general is not assigned to a camp due to its low competency ----//
436 
437 	Nation* ownNation = nation_array[nation_recno];
438 	int 	  rc = 0;
439 
440 	if( team_info->member_count <= 1 )
441 	{
442 		rc = 1;
443 	}
444 
445 	//--- if the skill of the general and the number of soldiers he commands is not large enough to justify building a new camp ---//
446 
447 	else if( skill.skill_level + team_info->member_count*4
448 				< 40 + ownNation->pref_keep_general/5 )					// 40 to 60
449 	{
450 		rc = 1;
451 	}
452 
453 	//-- think about splitting the team and assign them into other forts --//
454 
455 	else if( ownNation->ai_has_too_many_camp() )
456 	{
457 		rc = 1;
458 	}
459 
460 	//--------- demote the general to soldier and disband the troop -------//
461 
462 	if( rc )
463 	{
464 		set_rank(RANK_SOLDIER);
465 		return think_normal_human_action();
466 	}
467 
468 	return 0;
469 }
470 //---------- End of function Unit::think_general_action --------//
471 
472 
473 //--------- Begin of function Unit::think_leader_action --------//
474 //
475 // Think about the action of a leader (either a general or a king).
476 //
think_leader_action()477 int Unit::think_leader_action()
478 {
479 	Nation*   nationPtr = nation_array[nation_recno];
480 	FirmCamp *firmCamp, *bestCamp=NULL;
481 	int		 curRating, bestRating=10, delActionRecno=0;
482 	int		 curXLoc = next_x_loc(), curYLoc = next_y_loc();
483 	int		 curRegionId = world.get_region_id( curXLoc, curYLoc );
484 
485 	if( rank_id == RANK_KING )		// if this unit is the king, always assign it to a camp regardless of whether the king is a better commander than the existing one
486 		bestRating = -1000;
487 
488 	err_when( skill.skill_id != SKILL_LEADING );
489 
490 	//----- think about which camp to move to -----//
491 
492 	for( int i=nationPtr->ai_camp_count-1 ; i>=0 ; i-- )
493 	{
494 		firmCamp = (FirmCamp*) firm_array[ nationPtr->ai_camp_array[i] ];
495 
496 		if( firmCamp->region_id != curRegionId )
497 			continue;
498 
499 		//--- if the commander of this camp is the king, never replace him ---//
500 
501 		if( firmCamp->overseer_recno == nationPtr->king_unit_recno )
502 			continue;
503 
504 		//-------------------------------------//
505 
506 		int curLeadership = firmCamp->cur_commander_leadership();
507 		int newLeadership = firmCamp->new_commander_leadership(race_id, skill.skill_level);
508 
509 		curRating = newLeadership - curLeadership;
510 
511 		//-------------------------------------//
512 
513 		if( curRating > bestRating )
514 		{
515 			//--- if there is already somebody being assigned to it ---//
516 
517 			int actionRecno=0;
518 
519 			if( rank_id != RANK_KING )			// don't check this if the current unit is the king
520 			{
521 				actionRecno = nationPtr->is_action_exist(firmCamp->loc_x1, firmCamp->loc_y1,
522 								  -1, -1, ACTION_AI_ASSIGN_OVERSEER, FIRM_CAMP);
523 
524 				if( actionRecno && nationPtr->get_action(actionRecno)->processing_instance_count )
525 					continue;
526 			}
527 
528 			bestRating = curRating;
529 			bestCamp   = firmCamp;
530 			delActionRecno = actionRecno;
531 		}
532 	}
533 
534 	if( !bestCamp )
535 		return 0;
536 
537 	//----- delete an unprocessed queued action if there is any ----//
538 
539 	if( delActionRecno )
540 		nationPtr->del_action(delActionRecno);
541 
542 	//--------- move to the camp now ---------//
543 
544 	//-- if there is room in the camp to host all soldiers led by this general --//
545 
546 	if( team_info->member_count-1 <= MAX_WORKER-bestCamp->worker_count )
547 	{
548 		validate_team();
549 
550 		unit_array.assign( bestCamp->loc_x1, bestCamp->loc_y1, 0, COMMAND_AI,
551 								 team_info->member_unit_array, team_info->member_count );
552 		return 1;
553 	}
554 	else  //--- otherwise assign the general only ---//
555 	{
556 		return nationPtr->add_action(bestCamp->loc_x1, bestCamp->loc_y1, -1, -1, ACTION_AI_ASSIGN_OVERSEER, FIRM_CAMP, 1, sprite_recno);
557 	}
558 
559 	return 0;
560 }
561 //---------- End of function Unit::think_leader_action --------//
562 
563 
564 //--------- Begin of function Unit::think_normal_human_action --------//
565 
think_normal_human_action()566 int Unit::think_normal_human_action()
567 {
568 	if( home_camp_firm_recno )
569 		return 0;
570 
571 	if( leader_unit_recno &&
572 		 unit_array[leader_unit_recno]->is_visible() )		// if the unit is led by a commander, let the commander makes the decision. If the leader has been assigned to a firm, don't consider it as a leader anymore
573 	{
574 		return 0;
575 	}
576 
577 	err_when( !race_id );
578 	err_when( !nation_recno );
579 
580 	//---- think about assign the unit to a firm that needs workers ----//
581 
582 	Nation* ownNation = nation_array[nation_recno];
583 	Firm *firmPtr, *bestFirm=NULL;
584 	int  regionId = world.get_region_id( next_x_loc(), next_y_loc() );
585 	int  skillId  = skill.skill_id;
586 	int  skillLevel = skill.skill_level;
587 	int  i, curRating, bestRating=0;
588 	int  curXLoc = next_x_loc(), curYLoc = next_y_loc();
589 
590 	if( skill.skill_id )
591 	{
592 		for( i=firm_array.size() ; i>0 ; i-- )
593 		{
594 			if( firm_array.is_deleted(i) )
595 				continue;
596 
597 			firmPtr = firm_array[i];
598 
599 			if( firmPtr->nation_recno != nation_recno )
600 				continue;
601 
602 			if( firmPtr->region_id != regionId )
603 				continue;
604 
605 			curRating = 0;
606 
607 			if( skill.skill_id == SKILL_CONSTRUCTION )		// if this is a construction worker
608 			{
609 				if( firmPtr->builder_recno )			// assign the construction worker to this firm as an residental builder
610 					continue;
611 			}
612 			else
613 			{
614 				if( !firmPtr->worker_array ||
615 					 firmPtr->firm_skill_id != skillId )
616 				{
617 					continue;
618 				}
619 
620 				//----- if the firm is full of worker ------//
621 
622 				if( firmPtr->is_worker_full() )
623 				{
624 					//---- get the lowest skill worker of the firm -----//
625 
626 					Worker* workerPtr = firmPtr->worker_array;
627 					int	  minSkill=100;
628 
629 					for( int j=0 ; j<firmPtr->worker_count ; j++, workerPtr++ )
630 					{
631 						if( workerPtr->skill_level < minSkill )
632 							minSkill = workerPtr->skill_level;
633 					}
634 
635 					//------------------------------//
636 
637 					if( firmPtr->majority_race() == race_id )
638 					{
639 						if( skill.skill_level < minSkill+10 )
640 							continue;
641 					}
642 					else //-- for different race, only assign if the skill is significantly higher than the existing ones --//
643 					{
644 						if( skill.skill_level < minSkill+30 )
645 							continue;
646 					}
647 				}
648 				else
649 				{
650 					curRating += 300;		// if the firm is not full, rating + 300
651 				}
652 			}
653 
654 			//-------- calculate the rating ---------//
655 
656 			curRating += world.distance_rating( curXLoc, curYLoc, firmPtr->center_x, firmPtr->center_y );
657 
658 			if( firmPtr->majority_race() == race_id )
659 				curRating += 70;
660 
661 			curRating += (MAX_WORKER - firmPtr->worker_count) * 10;
662 
663 			//-------------------------------------//
664 
665 			if( curRating > bestRating )
666 			{
667 				bestRating = curRating;
668 				bestFirm   = firmPtr;
669 			}
670 		}
671 
672 		if( bestFirm )
673 		{
674 			assign(bestFirm->loc_x1, bestFirm->loc_y1);
675 			return 1;
676 		}
677 	}
678 
679 	//---- look for towns to assign to -----//
680 
681 	bestRating = 0;
682 	int  hasTownInRegion=0;
683 	Town *townPtr, *bestTown=NULL;
684 
685 	for( i=town_array.size() ; i>0 ; i-- )		// can't use ai_town_array[] because this function will be called by Unit::betray() when a unit defected to the player's kingdom
686 	{
687 		if( town_array.is_deleted(i) )
688 			continue;
689 
690 		townPtr = town_array[i];
691 
692 		if( townPtr->nation_recno != nation_recno )
693 			continue;
694 
695 		if( townPtr->region_id != regionId )
696 			continue;
697 
698 		hasTownInRegion = 1;
699 
700 		if( townPtr->population >= MAX_TOWN_POPULATION || !townPtr->is_base_town )
701 			continue;
702 
703 		//--- only assign to towns of the same race ---//
704 
705 		if( ownNation->pref_town_harmony > 50 )
706 		{
707 			if( townPtr->majority_race() != race_id )
708 				continue;
709 		}
710 
711 		//-------- calculate the rating ---------//
712 
713 		curRating = world.distance_rating(curXLoc, curYLoc, townPtr->center_x, townPtr->center_y );
714 
715 		curRating += 300 * townPtr->race_pop_array[race_id-1] / townPtr->population;		// racial homogenous bonus
716 
717 		curRating += MAX_TOWN_POPULATION - townPtr->population;
718 
719 		//-------------------------------------//
720 
721 		if( curRating > bestRating )
722 		{
723 			bestRating = curRating;
724 			bestTown   = townPtr;
725 		}
726 	}
727 
728 	if( bestTown )
729 	{
730 		assign(bestTown->loc_x1, bestTown->loc_y1);
731 		return 1;
732 	}
733 
734 	//----- if we don't have any existing towns in this region ----//
735 
736 	if( !hasTownInRegion )
737 	{
738 
739 		// --- if region is too small don't consider this area, stay in the island forever --//
740 		if( region_array[regionId]->region_stat_id == 0 )
741 			return 0;
742 
743 		//-- if we also don't have any existing camps in this region --//
744 
745 		if( region_array.get_region_stat(regionId)->camp_nation_count_array[nation_recno-1]==0 )
746 		{
747 			//---- try to build one if this unit can ----//
748 
749 			if( ownNation->cash > firm_res[FIRM_CAMP]->setup_cost &&
750 				 firm_res[FIRM_CAMP]->can_build(sprite_recno) &&
751 				 !leader_unit_recno )		// if this unit is commanded by a leader, let the leader build the camp
752 			{
753 				ai_build_camp();
754 			}
755 		}
756 		else		// if there is already a camp in this region, try to settle a new town next to the camp
757 		{
758 			ai_settle_new_town();
759 		}
760 
761 		return 1;	// if we don't have any town in this region, return 1, so this unit won't be resigned and so it can wait for other units to set up camps and villages later ---//
762 	}
763 
764 	return 0;
765 }
766 //---------- End of function Unit::think_normal_human_action --------//
767 
768 
769 //--------- Begin of function Unit::think_weapon_action --------//
770 
think_weapon_action()771 int Unit::think_weapon_action()
772 {
773 	//---- first try to assign the weapon to an existing camp ----//
774 
775 	if( think_assign_weapon_to_camp() )
776 		return 1;
777 
778 	//----- if no camp to assign, build a new one ------//
779 
780 	if( think_build_camp() )
781 		return 1;
782 
783 	return 0;
784 }
785 //---------- End of function Unit::think_weapon_action --------//
786 
787 
788 //--------- Begin of function Unit::think_assign_weapon_to_camp --------//
789 
think_assign_weapon_to_camp()790 int Unit::think_assign_weapon_to_camp()
791 {
792 	Nation 	*nationPtr = nation_array[nation_recno];
793 	FirmCamp *firmCamp, *bestCamp=NULL;
794 	int      curRating=0, bestRating=0;
795 	int		regionId = world.get_region_id( next_x_loc(), next_y_loc() );
796 	int		curXLoc = next_x_loc(), curYLoc = next_y_loc();
797 
798 	for( int i=0 ; i<nationPtr->ai_camp_count ; i++ )
799 	{
800 		firmCamp = (FirmCamp*) firm_array[ nationPtr->ai_camp_array[i] ];
801 
802 		if( firmCamp->region_id	!= regionId || firmCamp->is_worker_full() )
803 			continue;
804 
805 		//-------- calculate the rating ---------//
806 
807 		curRating = world.distance_rating(curXLoc, curYLoc, firmCamp->center_x, firmCamp->center_y );
808 
809 		curRating += (MAX_WORKER - firmCamp->worker_count) * 10;
810 
811 		//-------------------------------------//
812 
813 		if( curRating > bestRating )
814 		{
815 			bestRating = curRating;
816 			bestCamp   = firmCamp;
817 		}
818 	}
819 
820 	//-----------------------------------//
821 
822 	if( bestCamp )
823 	{
824 		assign(bestCamp->loc_x1, bestCamp->loc_y1);
825 		return 1;
826 	}
827 
828 	return 0;
829 }
830 //---------- End of function Unit::think_assign_weapon_to_camp --------//
831 
832 
833 //--------- Begin of function Unit::think_build_camp --------//
834 //
835 // Think about building a camp next to the town which is
836 // closest to the unit.
837 //
think_build_camp()838 int Unit::think_build_camp()
839 {
840 	//---- select a town to build the camp ---//
841 
842 	Nation* ownNation = nation_array[nation_recno];
843 	Town *townPtr, *bestTown=NULL;
844 	int   curRating=0, bestRating=0;
845 	int	regionId = world.get_region_id( next_x_loc(), next_y_loc() );
846 	int  	curXLoc = next_x_loc(), curYLoc = next_y_loc();
847 
848 	for( int i=ownNation->ai_town_count-1 ; i>=0 ; i-- )
849 	{
850 		townPtr = town_array[ ownNation->ai_town_array[i] ];
851 
852 		if( townPtr->region_id != regionId )
853 			continue;
854 
855 		if( !townPtr->is_base_town || townPtr->no_neighbor_space )
856 			continue;
857 
858 		curRating = world.distance_rating(curXLoc, curYLoc, townPtr->center_x, townPtr->center_y );
859 
860 		if( curRating > bestRating )
861 		{
862 			bestRating = curRating;
863 			bestTown   = townPtr;
864 		}
865 	}
866 
867 	if( bestTown )
868 		return bestTown->ai_build_neighbor_firm(FIRM_CAMP);
869 
870 	return 0;
871 }
872 //---------- End of function Unit::think_build_camp --------//
873 
874 
875 //--------- Begin of function Unit::think_reward --------//
876 
think_reward()877 int Unit::think_reward()
878 {
879 	Nation* ownNation = nation_array[nation_recno];
880 
881 	//----------------------------------------------------------//
882 	// The need to secure high loyalty on this unit is based on:
883 	// -its skill
884 	// -its combat level
885 	// -soldiers commanded by this unit
886 	//----------------------------------------------------------//
887 
888 	if( spy_recno && true_nation_recno() == nation_recno )		// if this is a spy of ours
889 	{
890 		return 0;		// Spy::think_reward() will handle this.
891 	}
892 
893 	int curLoyalty = loyalty;
894 	int neededLoyalty;
895 
896 	//----- if this unit is on a mission ------/
897 
898 	if( ai_action_id )
899 	{
900 		neededLoyalty = UNIT_BETRAY_LOYALTY+10;
901 	}
902 
903 	//----- otherwise only reward soldiers and generals ------//
904 
905 	else if( skill.skill_id == SKILL_LEADING )
906 	{
907 		//----- calculate the needed loyalty --------//
908 
909 		neededLoyalty = commanded_soldier_count()*5 + skill.skill_level;
910 
911 		if( unit_mode == UNIT_MODE_OVERSEE )		// if this unit is an overseer
912 		{
913 			if( loyalty < UNIT_BETRAY_LOYALTY )		// if this unit's loyalty is < betrayel level, reward immediately
914 			{
915 				reward(nation_recno);		// reward it immediatley if it's an overseer, don't check ai_should_spend()
916 				return 1;
917 			}
918 
919 			neededLoyalty += 30;
920 		}
921 
922 		neededLoyalty = MAX( UNIT_BETRAY_LOYALTY+10, neededLoyalty );		// 10 points above the betray loyalty level to prevent betrayal
923 		neededLoyalty = MIN( 100, neededLoyalty );
924 	}
925 	else
926 	{
927 		return 0;
928 	}
929 
930 	//------- if the loyalty is already high enough ------//
931 
932 	if( curLoyalty >= neededLoyalty )
933 		return 0;
934 
935 	//---------- see how many cash & profit we have now ---------//
936 
937 	int rewardNeedRating = neededLoyalty - curLoyalty;
938 
939 	if( curLoyalty < UNIT_BETRAY_LOYALTY+5 )
940 		rewardNeedRating += 50;
941 
942 	if( ownNation->ai_should_spend(rewardNeedRating) )
943 	{
944 		reward(nation_recno);
945 		return 1;
946 	}
947 
948 	return 0;
949 }
950 //---------- End of function Unit::think_reward --------//
951 
952 
953 
954 //--------- Begin of function Unit::ai_leader_being_attacked --------//
955 //
956 // This function is called when the king is under attack.
957 //
958 // <int> attackerUnitRecno - recno of the attacker unit.
959 //
ai_leader_being_attacked(int attackerUnitRecno)960 void Unit::ai_leader_being_attacked(int attackerUnitRecno)
961 {
962 	err_when( !team_info );
963 
964 	if( unit_array[attackerUnitRecno]->nation_recno == nation_recno )		// this can happen when the unit has just changed nation
965 		return;
966 
967 	//------------------------------------//
968 
969 	int rc=0, callIntervalDays;
970 
971 	if( rank_id == RANK_KING )
972 	{
973 		rc = 1;
974 		callIntervalDays = 7;
975 	}
976 	else if( rank_id == RANK_GENERAL )
977 	{
978 		rc = skill.skill_level >= 30 + (100-nation_array[nation_recno]->pref_keep_general)/2;		// 30 to 80
979 		callIntervalDays = 15;		// don't call too freqently
980 	}
981 
982 	if( rc )
983 	{
984 		if( info.game_date > team_info->ai_last_request_defense_date + callIntervalDays )
985 		{
986 			team_info->ai_last_request_defense_date = info.game_date;
987 			nation_array[nation_recno]->ai_defend(attackerUnitRecno);
988 		}
989 	}
990 }
991 //---------- End of function Unit::ai_leader_being_attacked --------//
992 
993 
994 //--------- Begin of function Unit::think_king_flee --------//
995 //
996 // Note: we still need to keep think_king_action() because
997 // 		between these two functions, a number of things
998 //			may be done, like returning home camp. We only
999 //			carry out actions in this function if the king
1000 //		   is in danger and urgently need to flee.
1001 //
think_king_flee()1002 int Unit::think_king_flee()
1003 {
1004 	if( force_move_flag && cur_action != SPRITE_IDLE )		// the king is already fleeing now
1005 		return 1;
1006 
1007 	//------- if the king is alone --------//
1008 
1009 	Nation* ownNation = nation_array[nation_recno];
1010 
1011 	//------------------------------------------------//
1012 	// When the king is alone and there is no assigned action OR
1013 	// when the king is injured, the king will flee
1014 	// back to its camp.
1015 	//------------------------------------------------//
1016 
1017 	if( ( team_info->member_count==0 && !ai_action_id ) ||
1018 		 hit_points < 125-ownNation->pref_military_courage/4 )
1019 	{
1020 		//------------------------------------------//
1021 		//
1022 		// If the king is currently under attack, flee
1023 		// to the nearest camp with the maximum protection.
1024 		//
1025 		//------------------------------------------//
1026 
1027 		Firm *firmCamp, *bestCamp=NULL;
1028 		int	curRating, bestRating=0;
1029 		int	curXLoc = next_x_loc(), curYLoc = next_y_loc();
1030 		int	curRegionId = world.get_region_id( curXLoc, curYLoc );
1031 
1032 		if( cur_action == SPRITE_ATTACK )
1033 		{
1034 			for( int i=ownNation->ai_camp_count-1 ; i>=0 ; i-- )
1035 			{
1036 				firmCamp = (FirmCamp*) firm_array[ ownNation->ai_camp_array[i] ];
1037 
1038 				if( firmCamp->region_id != curRegionId )
1039 					continue;
1040 
1041 				if( firmCamp->overseer_recno && rank_id!=RANK_KING )		// if there is already a commander in this camp. However if this is the king, than ingore this
1042 					continue;
1043 
1044 				curRating = world.distance_rating( curXLoc, curYLoc,
1045 								 firmCamp->center_x, firmCamp->center_y );
1046 
1047 				if( curRating > bestRating )
1048 				{
1049 					bestRating = curRating;
1050 					bestCamp   = firmCamp;
1051 				}
1052 			}
1053 
1054 		}
1055 		else if( home_camp_firm_recno )	// if there is a home for the king
1056 		{
1057 			bestCamp = firm_array[home_camp_firm_recno];
1058 		}
1059 
1060 		//------------------------------------//
1061 
1062 		if( bestCamp )
1063 		{
1064 			if( config.ai_aggressiveness > OPTION_LOW )
1065 				force_move_flag = 1;
1066 
1067 			assign( bestCamp->loc_x1, bestCamp->loc_y1 );
1068 		}
1069 		else	// if the king is neither under attack or has a home camp, then call the standard think_leader_action()
1070 		{
1071 			think_leader_action();
1072 		}
1073 
1074 		return cur_action != SPRITE_IDLE;
1075 	}
1076 
1077 	return 0;
1078 }
1079 //---------- End of function Unit::think_king_flee --------//
1080 
1081 
1082 //--------- Begin of function Unit::think_general_flee --------//
1083 
think_general_flee()1084 int Unit::think_general_flee()
1085 {
1086 	if( force_move_flag && cur_action != SPRITE_IDLE )		// the general is already fleeing now
1087 		return 1;
1088 
1089 	//------- if the general is alone --------//
1090 
1091 	Nation* ownNation = nation_array[nation_recno];
1092 
1093 	//------------------------------------------------//
1094 	// When the general is alone and there is no assigned action OR
1095 	// when the general is injured, the general will flee
1096 	// back to its camp.
1097 	//------------------------------------------------//
1098 
1099 	if( ( team_info->member_count==0 && !ai_action_id ) ||
1100 		 hit_points < max_hit_points * (75+ownNation->pref_military_courage/2) / 200 )		// 75 to 125 / 200
1101 	{
1102 		//------------------------------------------//
1103 		//
1104 		// If the general is currently under attack, flee
1105 		// to the nearest camp with the maximum protection.
1106 		//
1107 		//------------------------------------------//
1108 
1109 		Firm *firmCamp, *bestCamp=NULL;
1110 		int	curRating, bestRating=0;
1111 		int	curXLoc = next_x_loc(), curYLoc = next_y_loc();
1112 		int	curRegionId = world.get_region_id( curXLoc, curYLoc );
1113 
1114 		if( cur_action == SPRITE_ATTACK )
1115 		{
1116 			for( int i=ownNation->ai_camp_count-1 ; i>=0 ; i-- )
1117 			{
1118 				firmCamp = (FirmCamp*) firm_array[ ownNation->ai_camp_array[i] ];
1119 
1120 				if( firmCamp->region_id != curRegionId )
1121 					continue;
1122 
1123 				curRating = world.distance_rating( curXLoc, curYLoc,
1124 								 firmCamp->center_x, firmCamp->center_y );
1125 
1126 				if( curRating > bestRating )
1127 				{
1128 					bestRating = curRating;
1129 					bestCamp   = firmCamp;
1130 				}
1131 			}
1132 
1133 		}
1134 		else if( home_camp_firm_recno )	// if there is a home for the general
1135 		{
1136 			bestCamp = firm_array[home_camp_firm_recno];
1137 		}
1138 
1139 		//------------------------------------//
1140 
1141 		if( bestCamp )
1142 		{
1143 			if( bestCamp->overseer_recno )		// if there is already an overseer there, just move close to the camp for protection
1144 			{
1145 				if( config.ai_aggressiveness > OPTION_LOW )
1146 					force_move_flag = 1;
1147 
1148 				move_to( bestCamp->loc_x1, bestCamp->loc_y1 );
1149 			}
1150 			else
1151 				assign( bestCamp->loc_x1, bestCamp->loc_y1 );
1152 		}
1153 		else	// if the general is neither under attack or has a home camp, then call the standard think_leader_action()
1154 		{
1155 			think_leader_action();
1156 		}
1157 
1158 		return cur_action != SPRITE_IDLE;
1159 	}
1160 
1161 	return 0;
1162 }
1163 //---------- End of function Unit::think_general_flee --------//
1164 
1165 
1166 //--------- Begin of function Unit::ai_build_camp --------//
1167 //
1168 // Order this unit to build a camp in its region.
1169 //
ai_build_camp()1170 int Unit::ai_build_camp()
1171 {
1172 	//--- to prevent building more than one camp at the same time ---//
1173 
1174 	int     curRegionId = region_id();
1175 	Nation* ownNation = nation_array[nation_recno];
1176 
1177 	if( ownNation->is_action_exist( ACTION_AI_BUILD_FIRM, FIRM_CAMP, curRegionId ) )
1178 		return 0;
1179 
1180 	//------- locate a place for the camp --------//
1181 
1182 	FirmInfo* firmInfo = firm_res[FIRM_CAMP];
1183 	int 		 xLoc=0, yLoc=0;
1184 	char 	 	 teraMask = UnitRes::mobile_type_to_mask(UNIT_LAND);
1185 
1186 	if( world.locate_space_random(xLoc, yLoc, MAX_WORLD_X_LOC-1,
1187 		 MAX_WORLD_Y_LOC-1, firmInfo->loc_width+2, firmInfo->loc_height+2,   // leave at least one location space around the building
1188 		 MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC, curRegionId, 1, teraMask) )
1189 	{
1190 		return ownNation->add_action( xLoc, yLoc, -1, -1,
1191 					ACTION_AI_BUILD_FIRM, FIRM_CAMP, 1, sprite_recno );
1192 	}
1193 
1194 	return 0;
1195 }
1196 //---------- End of function Unit::ai_build_camp --------//
1197 
1198 
1199 //--------- Begin of function Unit::ai_settle_new_town --------//
1200 //
1201 // Settle a new village next to one of the camps in this region.
1202 //
ai_settle_new_town()1203 int Unit::ai_settle_new_town()
1204 {
1205 	//----- locate a suitable camp for the new town to settle next to ----//
1206 
1207 	Nation* 	 ownNation = nation_array[nation_recno];
1208 	FirmCamp* firmCamp, *bestCamp=NULL;
1209 	int	    curRegionId = region_id();
1210 	int		 curRating, bestRating=0;
1211 
1212 	for( int i=ownNation->ai_camp_count-1 ; i>=0 ; i-- )
1213 	{
1214 		firmCamp = (FirmCamp*) firm_array[ ownNation->ai_camp_array[i] ];
1215 
1216 		if( firmCamp->region_id != curRegionId )
1217 			continue;
1218 
1219 		curRating = firmCamp->total_combat_level();
1220 
1221 		if( curRating > bestRating )
1222 		{
1223 			bestRating = curRating;
1224 			bestCamp   = firmCamp;
1225 		}
1226 	}
1227 
1228 	if( !bestCamp )
1229 		return 0;
1230 
1231 	//--------- settle a new town now ---------//
1232 
1233 	int xLoc=bestCamp->loc_x1;
1234 	int yLoc=bestCamp->loc_y1;
1235 
1236 	if( world.locate_space(&xLoc, &yLoc, bestCamp->loc_x2, bestCamp->loc_y2,
1237 								  STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT,
1238 								  UNIT_LAND, curRegionId, 1 ) )					// 1-build flag
1239 	{
1240 		settle( xLoc, yLoc );
1241 		return 1;
1242 	}
1243 
1244 	return 0;
1245 }
1246 //---------- End of function Unit::ai_settle_new_town --------//
1247 
1248 
1249 //--------- Begin of function Unit::ai_handle_seek_path_fail --------//
1250 //
1251 // This function is used for handling cases when AI units are not
1252 // able to seek a path successfully.
1253 //
ai_handle_seek_path_fail()1254 int Unit::ai_handle_seek_path_fail()
1255 {
1256 	if( seek_path_fail_count < 5 )		// wait unit it has failed many times
1257 		return 0;
1258 
1259 	//----- try to move to a new location -----//
1260 
1261 	if( seek_path_fail_count==5 )
1262 	{
1263 		stop2();		// stop the unit and think for new action
1264 		return 0;
1265 	}
1266 
1267 	//--- if the seek path has failed too many times, resign the unit ---//
1268 
1269 	int resignFlag = 0;
1270 
1271 	if( rank_id == RANK_SOLDIER && !leader_unit_recno )
1272 	{
1273 		if( seek_path_fail_count>=7 )
1274 			resignFlag = 1;
1275 	}
1276 	else if( rank_id == RANK_GENERAL )
1277 	{
1278 		if( seek_path_fail_count >= 7+skill.skill_level/10 )
1279 			resignFlag = 1;
1280 	}
1281 
1282 	if( resignFlag && is_visible() )
1283 	{
1284 		resign(COMMAND_AI);
1285 		return 1;
1286 	}
1287 	else
1288 		return 0;
1289 }
1290 //---------- End of function Unit::ai_handle_seek_path_fail --------//
1291 
1292