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_ACT.CPP
22 //Description: AI - building firms
23
24 #include <ALL.h>
25 #include <OUNIT.h>
26 #include <OF_CAMP.h>
27 #include <OREGIONS.h>
28 #include <OCONFIG.h>
29 #include <OSITE.h>
30 #include <ONATION.h>
31
32
33 //--------- Begin of function Nation::think_build_firm --------//
34
think_build_firm()35 void Nation::think_build_firm()
36 {
37 if( !ai_should_build_mine() )
38 return;
39
40 //----- think building mine --------//
41
42 if( think_build_mine() )
43 return;
44
45 //---- if there is a mine action currently -----//
46
47 think_destroy_raw_site_guard();
48 }
49 //---------- End of function Nation::think_build_firm --------//
50
51
52 //--------- Begin of function Nation::think_build_mine --------//
53 //
think_build_mine()54 int Nation::think_build_mine()
55 {
56 //------- queue to build the new mine -------//
57
58 short xLoc, yLoc, refXLoc, refYLoc;
59
60 int rawId = seek_mine(xLoc, yLoc, refXLoc, refYLoc); //reference location is the raw material location
61
62 if( !rawId )
63 return 0;
64
65 //--- if we have a mine producing that raw type already ---//
66
67 if( raw_count_array[rawId-1] > 0 )
68 {
69 if( !ai_should_spend(20) ) // then it's not important to build it
70 return 0;
71 }
72
73 //-------------------------------------------//
74 // If the map is set to unexplored, wait for a
75 // reasonable amount of time before moving out
76 // to build the mine.
77 //-------------------------------------------//
78
79 if( !config.explore_whole_map )
80 {
81 int i;
82 for( i=0 ; i<ai_town_count ; i++ )
83 {
84 Town* townPtr = town_array[ ai_town_array[i] ];
85
86 int rawDistance = misc.points_distance(xLoc, yLoc, townPtr->center_x, townPtr->center_y);
87
88 if( info.game_date-info.game_start_date >
89 rawDistance * (5-config.ai_aggressiveness) / 5 ) // 3 to 5 / 5
90 {
91 break;
92 }
93 }
94
95 if( i==ai_town_count )
96 return 0;
97 }
98
99 return add_action(xLoc, yLoc, refXLoc, refYLoc, ACTION_AI_BUILD_FIRM, FIRM_MINE);
100 }
101 //---------- End of function Nation::think_build_mine --------//
102
103
104 //--------- Begin of function Nation::ai_should_build_mine --------//
105 //
ai_should_build_mine()106 int Nation::ai_should_build_mine()
107 {
108 //---- only build mines when it has enough population ----//
109
110 if( total_jobless_population < (100-pref_economic_development)/2 )
111 return 0;
112
113 if( total_jobless_population < 16 ) // only build mine when you have enough population to support the economic chain: mine + factory + camp
114 return 0;
115
116 if( site_array.untapped_raw_count==0 )
117 return 0;
118
119 if( !can_ai_build(FIRM_MINE) )
120 return 0;
121
122 //--- don't build additional mines unless we have enough population and demand to support it ----//
123
124 if( ai_mine_count == 1 )
125 {
126 if( true_profit_365days() < 0 && total_population < 40+pref_economic_development/5 )
127 return 0;
128 }
129
130 //-- if the nation is already in the process of building a new one --//
131
132 if( is_action_exist( ACTION_AI_BUILD_FIRM, FIRM_MINE ) )
133 return 0;
134
135 //--- if the population is low, make sure existing mines are in full production before building a new one ---//
136
137 if( total_jobless_population < 30 )
138 {
139 Firm* firmPtr;
140
141 for( int i=0 ; i<ai_mine_count ; i++ )
142 {
143 firmPtr = firm_array[ ai_mine_array[i] ];
144
145 if( firmPtr->worker_count < MAX_WORKER )
146 return 0;
147
148 if( firmPtr->linked_firm_count==0 && !firmPtr->no_neighbor_space ) // if the firm does not have any linked firms, that means the firm is still not in full operation
149 return 0;
150 }
151 }
152
153 return 1;
154 }
155 //---------- End of function Nation::ai_should_build_mine --------//
156
157
158 //--------- Begin of function Nation::ai_attack_unit_in_area --------//
159 //
160 // AI attacks all units that are not friendly to us within the given area.
161 //
162 // <int> xLoc1, yLoc1, xLoc2, yLoc2 - coordination of the area.
163 //
ai_attack_unit_in_area(int xLoc1,int yLoc1,int xLoc2,int yLoc2)164 void Nation::ai_attack_unit_in_area(int xLoc1, int yLoc1, int xLoc2, int yLoc2)
165 {
166 int enemyXLoc, enemyYLoc, enemyCombatLevel=0;
167 int enemyStatus = NATION_FRIENDLY;
168 Location* locPtr;
169 Unit* unitPtr;
170
171 //--------------------------------------------------//
172
173 for( int yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
174 {
175 for( int xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++ )
176 {
177 locPtr = world.get_loc(xLoc, yLoc);
178
179 if( !locPtr->has_unit(UNIT_LAND) )
180 continue;
181
182 unitPtr = unit_array[ locPtr->unit_recno(UNIT_LAND) ];
183
184 //--- if there is an idle unit on the mine building site ---//
185
186 if( unitPtr->cur_action != SPRITE_IDLE || unitPtr->nation_recno==0 )
187 continue;
188
189 //----- if this is our spy cloaked in another nation, reveal its true identity -----//
190
191 if( unitPtr->nation_recno != nation_recno &&
192 unitPtr->true_nation_recno() == nation_recno )
193 {
194 unitPtr->spy_change_nation(nation_recno, COMMAND_AI);
195 }
196
197 //--- if this is our own unit, order him to stay out of the building site ---//
198
199 if( unitPtr->nation_recno == nation_recno )
200 {
201 unitPtr->think_normal_human_action(); // send the unit to a firm or a town
202 }
203 else //--- if it is an enemy unit, attack it ------//
204 {
205 int nationStatus = get_relation_status(unitPtr->nation_recno);
206
207 if( nationStatus < enemyStatus ) // if the status is worse than the current target
208 {
209 enemyXLoc = xLoc;
210 enemyYLoc = yLoc;
211 enemyStatus = nationStatus;
212 enemyCombatLevel += (int) unitPtr->unit_power();
213 }
214 }
215 }
216 }
217
218 //--- if there are enemies on our firm building site, attack them ---//
219
220 if( enemyCombatLevel )
221 {
222 ai_attack_target( enemyXLoc, enemyYLoc, enemyCombatLevel );
223 }
224 }
225 //---------- End of function Nation::ai_attack_unit_in_area --------//
226
227
228 //--------- Begin of function Nation::think_destroy_raw_site_guard --------//
229 //
think_destroy_raw_site_guard()230 int Nation::think_destroy_raw_site_guard()
231 {
232 Site* sitePtr;
233 Location* locPtr;
234 Unit* unitPtr;
235
236 for( int i=site_array.size() ; i>0 ; i-- )
237 {
238 if( site_array.is_deleted(i) )
239 continue;
240
241 sitePtr = site_array[i];
242
243 //--- if there is already a mine built on this raw site ---//
244
245 if( sitePtr->has_mine )
246 continue;
247
248 //----- if there is a unit standing on this site -----//
249
250 locPtr = world.get_loc( sitePtr->map_x_loc, sitePtr->map_y_loc );
251
252 if( !locPtr->has_unit(UNIT_LAND) )
253 continue;
254
255 unitPtr = unit_array[ locPtr->unit_recno(UNIT_LAND) ];
256
257 if( unitPtr->cur_action != SPRITE_IDLE ) // only attack if this unit is idle
258 continue;
259
260 if( unitPtr->nation_recno == nation_recno ) // don't attack our own units
261 continue;
262
263 //------ check if we have a presence in this region ----//
264
265 // ####### patch begin Gilbert 16/3 ########//
266 //if( region_array.get_region_stat(sitePtr->region_id)->base_town_nation_count_array[nation_recno-1] == 0 )
267 // continue;
268 if( base_town_count_in_region(sitePtr->region_id) == 0 )
269 continue;
270 // ####### patch end Gilbert 16/3 ########//
271
272 //------ check the relationship with this unit ------//
273 //
274 // If we are friendly with this nation, don't attack it.
275 //
276 //---------------------------------------------------//
277
278 if( get_relation_status(unitPtr->nation_recno) >= NATION_FRIENDLY )
279 continue;
280
281 //--------- attack the enemy unit ---------//
282
283 int hasWar;
284 int enemyCombatLevel = mobile_defense_combat_level( sitePtr->map_x_loc,
285 sitePtr->map_y_loc, unitPtr->nation_recno, 1, hasWar );
286
287 if( enemyCombatLevel == - 1 ) // a war is going on here, don't attack this target
288 continue;
289
290 if( ai_attack_target(sitePtr->map_x_loc, sitePtr->map_y_loc, enemyCombatLevel, 0, 0, 0, 0, 1) ) // 1-use all camps
291 return 1;
292 }
293
294 return 0;
295 }
296 //---------- End of function Nation::think_destroy_raw_site_guard --------//
297
298
299 //--------- Begin of function Nation::ai_supported_inn_count --------//
300 //
301 // Return the number of inns this nation can support.
302 //
ai_supported_inn_count()303 int Nation::ai_supported_inn_count()
304 {
305 float fixedExpense = fixed_expense_365days();
306
307 int innCount = int( cash / 5000 * (100+pref_hire_unit) / 100 );
308
309 innCount = MIN(3, innCount); // maximum 3 inns, minimum 1 inn.
310
311 return MAX(1, innCount);
312 }
313 //---------- End of function Nation::ai_supported_inn_count --------//
314
315
316 //--------- Begin of function Nation::ai_has_should_close_camp --------//
317 //
318 // Return whether the this nation has any camps that should be closed.
319 //
320 // <int> regionId - only camps in this region are counted.
321 //
ai_has_should_close_camp(int regionId)322 int Nation::ai_has_should_close_camp(int regionId)
323 {
324 //--- if this nation has some firms going to be closed ---//
325
326 if( firm_should_close_array[FIRM_CAMP-1] > 0 )
327 {
328 //--- check if any of them are in the same region as the current town ---//
329
330 for( int i=ai_camp_count-1 ; i>=0 ; i-- )
331 {
332 FirmCamp* firmCamp = (FirmCamp*) firm_array[ ai_camp_array[i] ];
333
334 if( firmCamp->should_close_flag && firmCamp->region_id == regionId )
335 {
336 return 1;
337 }
338 }
339 }
340
341 return 0;
342 }
343 //---------- End of function Nation::ai_has_should_close_camp --------//
344