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