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   : OAI_MAIN.CPP
22 //Description: AI - main functions
23 
24 #include <OSYS.h>
25 #include <ONATION.h>
26 #include <OWORLD.h>
27 #include <OGAME.h>
28 #include <OSPY.h>
29 #include <OCONFIG.h>
30 #include <OUNIT.h>
31 #include <OFIRM.h>
32 #include <OTOWN.h>
33 #include <OTALKRES.h>
34 #include <OF_MINE.h>
35 #include <OINFO.h>
36 #include <OLOG.h>
37 
38 //--------- Begin of function Nation::Nation --------//
39 
Nation()40 Nation::Nation() : action_array( sizeof(ActionNode), 30 )
41 {
42 	ai_town_array = NULL;
43 }
44 //---------- End of function Nation::Nation --------//
45 
46 
47 //--------- Begin of function Nation::~Nation --------//
48 
~Nation()49 Nation::~Nation()
50 {
51 	err_when( nation_recno );     // deinit() must be called first before this destructor is called
52 }
53 //---------- End of function Nation::~Nation --------//
54 
55 
56 //--------- Begin of function Nation::init --------//
init(int nationType,int raceId,int colorSchemeId,uint32_t playerId)57 void Nation::init(int nationType, int raceId, int colorSchemeId, uint32_t playerId)
58 {
59 	NationBase::init(nationType, raceId, colorSchemeId, playerId);
60 
61 	//----- init other AI vars -----//
62 
63 	last_action_id = 0;
64 
65 	ai_capture_enemy_town_recno = 0;
66 	ai_capture_enemy_town_start_attack_date = 0;
67 	ai_last_defend_action_date = 0;
68 
69 	memset( firm_should_close_array, 0, sizeof(firm_should_close_array) );
70 
71 	ai_base_town_count = 0;
72 
73 	attack_camp_count = 0;
74 
75 	//------ init AI info arrays -----//
76 
77 	init_all_ai_info();
78 
79 	//----- init AI personality ----//
80 
81 	init_personalty();
82 }
83 //---------- End of function Nation::init --------//
84 
85 
86 //--------- Begin of function Nation::deinit --------//
87 
deinit()88 void Nation::deinit()
89 {
90 	NationBase::deinit();
91 
92 	deinit_all_ai_info();
93 }
94 //---------- End of function Nation::deinit --------//
95 
96 
97 //--------- Begin of function Nation::init_all_ai_info --------//
98 
init_all_ai_info()99 void Nation::init_all_ai_info()
100 {
101 	err_when( ai_town_array );
102 
103 	init_ai_info(&ai_town_array, ai_town_count, ai_town_size, AI_TOWN_INIT_SIZE);
104 
105 	init_ai_info(&ai_base_array, ai_base_count, ai_base_size, AI_BASE_INIT_SIZE);
106 	init_ai_info(&ai_mine_array, ai_mine_count, ai_mine_size, AI_MINE_INIT_SIZE);
107 	init_ai_info(&ai_factory_array, ai_factory_count, ai_factory_size, AI_FACTORY_INIT_SIZE);
108 	init_ai_info(&ai_market_array, ai_market_count, ai_market_size, AI_MARKET_INIT_SIZE);
109 	init_ai_info(&ai_inn_array, ai_inn_count, ai_inn_size, AI_INN_INIT_SIZE);
110 	init_ai_info(&ai_camp_array, ai_camp_count, ai_camp_size, AI_CAMP_INIT_SIZE);
111 	init_ai_info(&ai_research_array, ai_research_count, ai_research_size, AI_RESEARCH_INIT_SIZE);
112 	init_ai_info(&ai_war_array, ai_war_count, ai_war_size, AI_WAR_INIT_SIZE);
113 	init_ai_info(&ai_harbor_array, ai_harbor_count, ai_harbor_size, AI_HARBOR_INIT_SIZE);
114 
115 	init_ai_info(&ai_caravan_array, ai_caravan_count, ai_caravan_size, AI_CARAVAN_INIT_SIZE);
116 	init_ai_info(&ai_ship_array, ai_ship_count, ai_ship_size, AI_SHIP_INIT_SIZE);
117 	init_ai_info(&ai_general_array, ai_general_count, ai_general_size, AI_GENERAL_INIT_SIZE);
118 }
119 //---------- End of function Nation::init_all_ai_info --------//
120 
121 
122 //--------- Begin of function Nation::init_ai_info --------//
123 //
124 // <short**> aiInfoArrayPtr  - poniter to the AI info array.
125 // <short&>  aiInfoCount  - the count of the AI info array.
126 // <short&>  aiInfoSize   - the size of the AI info array.
127 // <int>     arrayInitSize - the init size of the array.
128 //
init_ai_info(short ** aiInfoArrayPtr,short & aiInfoCount,short & aiInfoSize,int arrayInitSize)129 void Nation::init_ai_info(short** aiInfoArrayPtr, short& aiInfoCount, short& aiInfoSize, int arrayInitSize )
130 {
131 	*aiInfoArrayPtr = (short*) mem_add( sizeof(short) * arrayInitSize );
132 
133 	memset( *aiInfoArrayPtr, 0, sizeof(short) * arrayInitSize );
134 
135 	aiInfoCount = 0;
136 	aiInfoSize  = arrayInitSize;
137 }
138 //---------- End of function Nation::init_ai_info --------//
139 
140 
141 //--------- Begin of function Nation::deinit_all_ai_info --------//
142 
deinit_all_ai_info()143 void Nation::deinit_all_ai_info()
144 {
145 	err_when( !ai_town_array );
146 
147 	//------- debug checking -------//
148 
149 #ifdef DEBUG
150 	if( !sys.signal_exit_flag )
151 	{
152 		err_when( ai_town_count > 0 );
153 		err_when( ai_base_town_count > 0 );
154 
155 		err_when( ai_base_count > 0 );
156 		err_when( ai_mine_count > 0 );
157 		err_when( ai_factory_count > 0 );
158 		err_when( ai_market_count > 0 );
159 		err_when( ai_inn_count > 0 );
160 		err_when( ai_camp_count > 0 );
161 		err_when( ai_research_count > 0 );
162 		err_when( ai_war_count > 0 );
163 		err_when( ai_harbor_count > 0 );
164 
165 		err_when( ai_caravan_count > 0 );
166 		err_when( ai_ship_count > 0 );
167 		err_when( ai_general_count > 0 );
168 	}
169 #endif
170 
171 	//------- release array from memory -------//
172 
173 	mem_del(ai_town_array);
174 
175 	mem_del(ai_base_array);
176 	mem_del(ai_mine_array);
177 	mem_del(ai_factory_array);
178 	mem_del(ai_market_array);
179 	mem_del(ai_inn_array);
180 	mem_del(ai_camp_array);
181 	mem_del(ai_research_array);
182 	mem_del(ai_war_array);
183 	mem_del(ai_harbor_array);
184 
185 	mem_del(ai_caravan_array);
186 	mem_del(ai_ship_array);
187 	mem_del(ai_general_array);
188 }
189 //---------- End of function Nation::deinit_all_ai_info --------//
190 
191 
192 //--------- Begin of function Nation::init_personalty --------//
init_personalty()193 void Nation::init_personalty()
194 {
195 	pref_force_projection     = misc.random(101);
196 	pref_military_development = misc.random(101);
197 	pref_economic_development = 100-pref_military_development;
198 	pref_inc_pop_by_capture   = misc.random(101);
199 	pref_inc_pop_by_growth    = 100-pref_inc_pop_by_capture;
200 	pref_peacefulness         = misc.random(101);
201 	pref_military_courage     = misc.random(101);
202 	pref_territorial_cohesiveness = misc.random(101);
203 	pref_trading_tendency     = misc.random(101);
204 	pref_allying_tendency     = misc.random(101);
205 	pref_honesty              = misc.random(101);
206 	pref_town_harmony         = misc.random(101);
207 	pref_loyalty_concern      = misc.random(101);
208 	pref_forgiveness          = misc.random(101);
209 	pref_collect_tax          = misc.random(101);
210 	pref_hire_unit            = misc.random(101);
211 	pref_use_weapon           = misc.random(101);
212 	pref_keep_general         = misc.random(101);
213 	pref_keep_skilled_unit    = misc.random(101);
214 	pref_diplomacy_retry      = misc.random(101);
215 	pref_attack_monster       = misc.random(101);
216 	pref_spy                  = misc.random(101);
217 	pref_counter_spy          = misc.random(101);
218 	pref_cash_reserve         = misc.random(101);
219 	pref_food_reserve         = misc.random(101);
220 	pref_use_marine           = misc.random(101);
221 	pref_unit_chase_distance  = 15+misc.random(15);
222 	pref_repair_concern       = misc.random(101);
223 	pref_scout		  = misc.random(101);
224 }
225 //---------- End of function Nation::init_personalty --------//
226 
227 
228 //--------- Begin of function Nation::process_ai --------//
process_ai()229 void Nation::process_ai()
230 {
231 	//-*********** simulate aat ************-//
232 #ifdef DEBUG
233 	if(debug_sim_game_type)
234 		return;
235 #endif
236 	//-*********** simulate aat ************-//
237 
238 	if( config.disable_ai_flag || game.game_mode == GAME_TEST )
239 		return;
240 
241 	//---- if the king has just been killed ----//
242 
243 	int nationRecno = nation_recno;
244 
245 	if( !king_unit_recno )
246 	{
247 		if( think_succeed_king() )
248 			return;
249 
250 		if( think_surrender() )
251 			return;
252 
253 		defeated();
254 		return;
255 	}
256 
257 	//-------- process main AI actions ---------//
258 
259    process_ai_main();
260 
261 	if( nation_array.is_deleted(nationRecno) )		// the nation can have surrendered
262 		return;
263 
264 	//------ process queued diplomatic messges first --------//
265 
266 	// ##### begin Gilbert 4/10 ######//
267    if( (info.game_date-nation_recno)%3 == 0 )
268 	{
269 		LOG_MSG("begin process_action(0,ACTION_AI_PROCESS_TALK_MSG)");
270 		process_action(0, ACTION_AI_PROCESS_TALK_MSG);
271 		LOG_MSG("end process_action(0,ACTION_AI_PROCESS_TALK_MSG)");
272 		LOG_MSG(misc.get_random_seed());
273 
274 		if( nation_array.is_deleted(nationRecno) )		// the nation can have surrendered
275 			return;
276 	}
277 
278 	// ##### end Gilbert 4/10 ######//
279 
280    //--------- process queued actions ----------//
281 
282 	// ##### begin Gilbert 4/10 ######//
283    if( (info.game_date-nation_recno)%3 == 0 )
284 	{
285 		LOG_MSG("begin process_action()");
286 		process_action();
287 		LOG_MSG("end process_action()");
288 		LOG_MSG(misc.get_random_seed());
289 
290 		if( nation_array.is_deleted(nationRecno) )		// the nation can have surrendered
291 			return;
292 	}
293 	// ##### end Gilbert 4/10 ######//
294 
295 	//--- process action that are on-going and need continous checking ---//
296 
297 	process_on_going_action();
298 
299 	//--------- cheat ---------//
300 	//
301 	// In tutorial mode only so that your opponent won't surrender
302 	// and you won't go to the end game screen.
303 	//
304 	//-------------------------//
305 
306 	if( game.game_mode == GAME_TUTORIAL )
307 	{
308 		if( cash < 100 )
309 			add_cheat( (float)200+misc.random(500) );
310 
311 		if( food < 100 )
312 			food += 1000;
313 	}
314 
315 	//----- think about updating relationship with other nations -----//
316 
317 	if( info.game_date%360 == nation_recno%360 )
318 		ai_improve_relation();
319 
320 	//------ think about surrendering -------//
321 
322 	if( info.game_date%60 == nation_recno%60 )
323 	{
324 		if( think_surrender() )
325 			return;
326 
327 		if( think_unite_against_big_enemy() )
328 			return;
329 	}
330 }
331 //---------- End of function Nation::process_ai --------//
332 
333 
334 //--------- Begin of function Nation::process_on_going_action --------//
335 //
336 // Process action that are on-going and need continous checking.
337 //
process_on_going_action()338 void Nation::process_on_going_action()
339 {
340 	//--- if the nation is in the process of trying to capture an enemy town ---//
341 
342 	if( ai_capture_enemy_town_recno )
343 	{
344 		if( info.game_date%5 == nation_recno%5 )
345 			think_capturing_enemy_town();
346 	}
347 
348 	//----- if the nation is in the process of attacking a target ----//
349 
350 	if( attack_camp_count > 0 )
351 		ai_attack_target_execute(1);
352 }
353 //---------- End of function Nation::process_on_going_action --------//
354 
355 
356 //------- Begin of function Nation::process_ai_main --------//
357 //
process_ai_main()358 void Nation::process_ai_main()
359 {
360 #if defined(DEBUG) && defined(ENABLE_LOG)
361    String debugStr;
362    debugStr = "Nation ";
363    debugStr += nation_recno;
364 #endif
365 
366 	static short intervalDaysArray[] = { 90, 30, 15, 15 };
367 
368 	int intervalDays = intervalDaysArray[config.ai_aggressiveness-OPTION_LOW];
369 
370 	if( game.game_mode == GAME_TUTORIAL )
371 		intervalDays = 120;
372 
373 	switch( (info.game_date-nation_recno*4) % intervalDays )
374    {
375       case 0:
376 #if defined(DEBUG) && defined(ENABLE_LOG)
377          debugStr += " think_build_firm";
378 #endif
379          think_build_firm();
380          break;
381 
382       case 1:
383 #if defined(DEBUG) && defined(ENABLE_LOG)
384          debugStr += " think_trading";
385 #endif
386          think_trading();
387          break;
388 
389       case 2:
390 #if defined(DEBUG) && defined(ENABLE_LOG)
391          debugStr += " think_capture";
392 #endif
393 			think_capture();
394 			break;
395 
396 		case 3:
397 #if defined(DEBUG) && defined(ENABLE_LOG)
398 			debugStr += " think_explore";
399 #endif
400 			think_explore();
401 			break;
402 
403 		case 4:        // think about expanding its military force
404 #if defined(DEBUG) && defined(ENABLE_LOG)
405 			debugStr += " think_military";
406 #endif
407 			think_military();
408 			break;
409 
410 		case 5:
411 #if defined(DEBUG) && defined(ENABLE_LOG)
412 			debugStr += " think_secret_attack";
413 #endif
414 			think_secret_attack();
415 			break;
416 
417 		case 6:
418 #if defined(DEBUG) && defined(ENABLE_LOG)
419 			debugStr += " think_attack_monster";
420 #endif
421 			think_attack_monster();
422 			break;
423 
424 		case 7:
425 #if defined(DEBUG) && defined(ENABLE_LOG)
426 			debugStr += " think_diplomacy";
427 #endif
428 			think_diplomacy();
429 			break;
430 
431 		case 8:
432 #if defined(DEBUG) && defined(ENABLE_LOG)
433 			debugStr += " think_marine";
434 #endif
435 			think_marine();
436 			break;
437 
438 		case 9:
439 #if defined(DEBUG) && defined(ENABLE_LOG)
440 			debugStr += " think_grand_plan";
441 #endif
442 			think_grand_plan();
443 			break;
444 
445 		case 10:
446 #if defined(DEBUG) && defined(ENABLE_LOG)
447 			debugStr += " think_reduce_expense";
448 #endif
449 			think_reduce_expense();
450 			break;
451 
452 		case 11:
453 #if defined(DEBUG) && defined(ENABLE_LOG)
454 			debugStr += " think_town";
455 #endif
456 			think_town();
457 			break;
458 	}
459 
460 	LOG_MSG(debugStr);
461 	LOG_MSG(misc.get_random_seed());
462 }
463 //---------- End of function Nation::process_ai_main --------//
464 
465 
466 //--------- Begin of function Nation::think_explore --------//
467 
think_explore()468 void Nation::think_explore()
469 {
470 }
471 //---------- End of function Nation::think_explore --------//
472 
473 
474 //-------- Begin of function Nation::think_succeed_king --------//
475 //
476 // return: <int> 1 - a unit succeed the king
477 //               0 - no unit available for succeeding the king,
478 //                   the nation is defeated.
479 //
think_succeed_king()480 int Nation::think_succeed_king()
481 {
482    int  i, curRating, bestRating=0;
483    Unit *unitPtr, *bestUnitPtr=NULL;
484    Firm *firmPtr, *bestFirmPtr=NULL;
485    int  bestWorkerId=0;
486 
487    //---- try to find the best successor from mobile units ----//
488 
489    for( i=unit_array.size() ; i>0 ; i-- )
490    {
491       if( unit_array.is_deleted(i) )
492          continue;
493 
494       unitPtr = unit_array[i];
495 
496       if( unitPtr->nation_recno != nation_recno || !unitPtr->race_id )
497          continue;
498 
499       if( !unitPtr->is_visible() && unitPtr->unit_mode != UNIT_MODE_OVERSEE )
500          continue;
501 
502       err_when( unitPtr->skill.combat_level<= 0 );
503 
504       curRating = 0;
505 
506 		if( unitPtr->race_id == race_id )
507 			curRating += 50;
508 
509       if( unitPtr->rank_id == RANK_GENERAL )
510          curRating += 50;
511 
512 		if( unitPtr->skill.skill_id == SKILL_LEADING )
513          curRating += unitPtr->skill.skill_level;
514 
515       if( curRating > bestRating )
516       {
517          bestRating  = curRating;
518          bestUnitPtr = unitPtr;
519       }
520    }
521 
522    //---- try to find the best successor from military camps ----//
523 
524    for( i=firm_array.size() ; i>0 ; i-- )
525    {
526       if( firm_array.is_deleted(i) )
527          continue;
528 
529       firmPtr = firm_array[i];
530 
531       if( firmPtr->nation_recno != nation_recno )
532          continue;
533 
534       //------ only military camps -------//
535 
536       if( firmPtr->firm_id == FIRM_CAMP )
537       {
538          Worker* workerPtr = firmPtr->worker_array;
539 
540          for(int j=1 ; j<=firmPtr->worker_count ; j++, workerPtr++ )
541          {
542             if( !workerPtr->race_id )
543                continue;
544 
545             curRating = 0;
546 
547             if( workerPtr->race_id == race_id )
548                curRating += 50;
549 
550 				if( workerPtr->rank_id == RANK_GENERAL )
551                curRating += 50;
552 
553             if( workerPtr->skill_id == SKILL_LEADING )
554                curRating += workerPtr->skill_level;
555 
556             if( curRating > bestRating )
557             {
558                bestRating   = curRating;
559                bestUnitPtr  = NULL;
560                bestFirmPtr  = firmPtr;
561                bestWorkerId = j;
562             }
563          }
564       }
565    }
566 
567    //------- if the best successor is a mobile unit -------//
568 
569    if( bestUnitPtr )
570    {
571       //-- if the unit is in a command base or seat of power, mobilize it --//
572 
573       if( !bestUnitPtr->is_visible() )
574       {
575          err_when( bestUnitPtr->unit_mode != UNIT_MODE_OVERSEE );
576 
577          firm_array[bestUnitPtr->unit_mode_para]->mobilize_overseer();
578 
579          err_when( bestUnitPtr->skill.combat_level<= 0 );
580       }
581 
582       //---------- succeed the king -------------//
583 
584       if( bestUnitPtr->is_visible() )     // it may still be not visible if there is no space for the unit to be mobilized
585       {
586          if( bestUnitPtr->spy_recno && bestUnitPtr->true_nation_recno() == nation_recno )    // if this is a spy and he's our spy
587             spy_array[bestUnitPtr->spy_recno]->drop_spy_identity();                          // revert the spy to a normal unit
588 
589          succeed_king( bestUnitPtr->sprite_recno );
590          return 1;
591       }
592    }
593 
594    //------- if the best successor is a soldier in a camp -------//
595 
596    if( bestFirmPtr )
597    {
598 		int unitRecno = bestFirmPtr->mobilize_worker(bestWorkerId, COMMAND_AI);
599 
600       if( unitRecno )
601       {
602          succeed_king( unitRecno );
603          return 1;
604       }
605    }
606 
607    //--- if stil not found here, then try to locate the sucessor from villages ---//
608 
609    Town* townPtr;
610 
611    for( i=town_array.size() ; i>0 ; i-- )
612    {
613 		if( town_array.is_deleted(i) )
614          continue;
615 
616       townPtr = town_array[i];
617 
618       if( townPtr->nation_recno != nation_recno )
619          continue;
620 
621       if( townPtr->recruitable_race_pop(race_id, 0) > 0 )   // if this town has people with the same race as the original king
622       {
623          int unitRecno = townPtr->mobilize_town_people(race_id, 1, 0);     // 1-dec pop, 0-don't mobilize spies
624 
625 			if( unitRecno )
626 			{
627 				succeed_king( unitRecno );
628 				return 1;
629 			}
630 		}
631 	}
632 
633 	return 0;
634 }
635 //---------- End of function Nation::think_succeed_king ---------//
636 
637 
638 //--------- Begin of function Nation::ai_improve_relation --------//
639 //
640 // This function is called once every year.
641 //
ai_improve_relation()642 void Nation::ai_improve_relation()
643 {
644 	NationRelation* nationRelation;
645 
646 	for( int i=nation_array.size() ; i>0 ; i-- )
647 	{
648 		if( nation_array.is_deleted(i) )
649 			continue;
650 
651 		nationRelation = get_relation(i);
652 
653 		if( nationRelation->status == NATION_HOSTILE )
654 			continue;
655 
656 		//--- It improves the AI relation with nations that have trade with us. ---//
657 
658 		change_ai_relation_level( i, trade_rating(i) / 10 );
659 
660 		//--- decrease the started_war_on_us_count once per year, gradually forgiving other nations' wrong doing ---//
661 
662 		if( nationRelation->started_war_on_us_count > 0
663 			 && misc.random(5-pref_forgiveness/20) > 0 )
664 		{
665 			nationRelation->started_war_on_us_count--;
666 		}
667 	}
668 }
669 //---------- End of function Nation::ai_improve_relation --------//
670 
671 
672