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