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
22 //Filename : OAI_INFO.CPP
23 //Description : AI - A.I. info structure
24
25 #include <OSYS.h>
26 #include <OTOWN.h>
27 #include <OF_MARK.h>
28 #include <OU_CARA.h>
29 #include <ONATION.h>
30
31
32 //--------- Begin of function Nation::update_ai_firm_array --------//
33 //
34 // <int> firmId - determine which firm array to be returned
35 //
36 // <int> actionType: 1 - add a record to the array
37 // 0 - no addition or deletion, just return
38 // -1 - del a record from the array
39 //
40 // <int> actionRecno : the recno to be deleted, if actionType is -1.
41 // the recno to be added, if actionType is 1.
42 // <int> arrayCount: for return the count of the AI info array
43 //
update_ai_firm_array(int firmId,int actionType,int actionRecno,int & arrayCount)44 short* Nation::update_ai_firm_array(int firmId, int actionType, int actionRecno, int& arrayCount)
45 {
46 short* rc;
47
48 switch(firmId)
49 {
50 case FIRM_BASE:
51 rc = update_ai_array(ai_base_count, ai_base_size, &ai_base_array,
52 AI_BASE_INC_SIZE, actionType, actionRecno);
53 arrayCount = ai_base_count;
54 break;
55
56 case FIRM_CAMP:
57 rc = update_ai_array(ai_camp_count, ai_camp_size, &ai_camp_array,
58 AI_CAMP_INC_SIZE, actionType, actionRecno);
59 arrayCount = ai_camp_count;
60 break;
61
62 case FIRM_FACTORY:
63 rc = update_ai_array(ai_factory_count, ai_factory_size, &ai_factory_array,
64 AI_FACTORY_INC_SIZE, actionType, actionRecno);
65 arrayCount = ai_factory_count;
66 break;
67
68 case FIRM_MARKET:
69 rc = update_ai_array(ai_market_count, ai_market_size, &ai_market_array,
70 AI_MARKET_INC_SIZE, actionType, actionRecno);
71 arrayCount = ai_market_count;
72 break;
73
74 case FIRM_INN:
75 rc = update_ai_array(ai_inn_count, ai_inn_size, &ai_inn_array,
76 AI_INN_INC_SIZE, actionType, actionRecno);
77 arrayCount = ai_inn_count;
78 break;
79
80 case FIRM_MINE:
81 rc = update_ai_array(ai_mine_count, ai_mine_size, &ai_mine_array,
82 AI_MINE_INC_SIZE, actionType, actionRecno);
83 arrayCount = ai_mine_count;
84 break;
85
86 case FIRM_RESEARCH:
87 rc = update_ai_array(ai_research_count, ai_research_size, &ai_research_array,
88 AI_RESEARCH_INC_SIZE, actionType, actionRecno);
89 arrayCount = ai_research_count;
90 break;
91
92 case FIRM_WAR_FACTORY:
93 rc = update_ai_array(ai_war_count, ai_war_size, &ai_war_array,
94 AI_WAR_INC_SIZE, actionType, actionRecno);
95 arrayCount = ai_war_count;
96 break;
97
98 case FIRM_HARBOR:
99 rc = update_ai_array(ai_harbor_count, ai_harbor_size, &ai_harbor_array,
100 AI_HARBOR_INC_SIZE, actionType, actionRecno);
101 arrayCount = ai_harbor_count;
102 break;
103
104 default:
105 err_here();
106 return 0;
107 }
108
109 return rc;
110 }
111 //---------- End of function Nation::update_ai_firm_array --------//
112
113
114 //--------- Begin of function Nation::update_ai_array --------//
115 //
116 // <short&> aiInfoCount - the count of the AI info array.
117 // <short&> aiInfoSize - the size of the AI info array.
118 // <short**> aiInfoArray - poniter to the AI info array.
119 // <int> arrayIncSize - the increment size of the array.
120 //
121 // <int> actionType: 1 - add a record to the array
122 // 0 - no addition or deletion, just return
123 // -1 - del a record from the array
124 //
125 // [int] actionRecno : the recno to be deleted, if actionType is -1.
126 // the recno to be added, if actionType is 1.
127 //
update_ai_array(short & aiInfoCount,short & aiInfoSize,short ** aiInfoArrayPtr,int arrayIncSize,int actionType,int actionRecno)128 short* Nation::update_ai_array(short& aiInfoCount, short& aiInfoSize,
129 short** aiInfoArrayPtr, int arrayIncSize, int actionType, int actionRecno)
130 {
131 err_when( aiInfoCount<0 );
132 err_when( aiInfoCount > aiInfoSize );
133 err_when( actionType<-1 || actionType>1 );
134
135 short* aiInfoArray = *aiInfoArrayPtr;
136
137 if( actionType == -1 )
138 {
139 short* aiInfoPtr = aiInfoArray;
140
141 for( int i=0 ; i<aiInfoCount ; i++, aiInfoPtr++ )
142 {
143 if( *aiInfoPtr == actionRecno )
144 {
145 if( i+1==aiInfoCount ) // the record to be deleted is the last record
146 {
147 *aiInfoPtr = 0;
148 }
149 else // the record to be deleted is not the last record, somewhere in the array
150 {
151 //---- copy the last record to this slot which has been marked for deletion
152
153 *aiInfoPtr = aiInfoArray[aiInfoCount-1];
154 aiInfoArray[aiInfoCount-1] = 0;
155 }
156
157 aiInfoCount--;
158 return aiInfoArray;
159 }
160 }
161
162 err_here(); // not found, this shouldn't happen.
163 }
164 else if( actionType == 1 )
165 {
166 if( aiInfoCount == aiInfoSize )
167 {
168 #ifdef DEBUG
169 short saveDate1 = aiInfoArray[0]; // for vertification of resizing that old data are kept
170 short saveDate2 = aiInfoArray[aiInfoCount-1];
171 #endif
172
173 aiInfoSize += arrayIncSize;
174
175 *aiInfoArrayPtr = (short*) mem_resize( aiInfoArray, aiInfoSize*sizeof(short) );
176
177 aiInfoArray = *aiInfoArrayPtr;
178
179 err_when( saveDate1 != aiInfoArray[0] ); // for vertification of resizing that old data are kept
180 err_when( saveDate2 != aiInfoArray[aiInfoCount-1] );
181 }
182
183 aiInfoArray[aiInfoCount++] = actionRecno;
184 }
185
186 return aiInfoArray;
187 }
188 //---------- End of function Nation::update_ai_array --------//
189
190
191 //--------- Begin of function Nation::add_firm_info --------//
192 //
add_firm_info(char firmId,short firmRecno)193 void Nation::add_firm_info(char firmId, short firmRecno)
194 {
195 err_when( !firmId || !firmRecno );
196
197 int aiFirmCount;
198
199 update_ai_firm_array(firmId, 1, firmRecno, aiFirmCount);
200 }
201 //---------- End of function Nation::add_firm_info --------//
202
203
204 //--------- Begin of function Nation::del_firm_info --------//
205
del_firm_info(char firmId,short firmRecno)206 void Nation::del_firm_info(char firmId, short firmRecno)
207 {
208 err_when( !firmId || !firmRecno );
209
210 int aiFirmCount;
211
212 update_ai_firm_array(firmId, -1, firmRecno, aiFirmCount);
213 }
214 //---------- End of function Nation::del_firm_info --------//
215
216
217 //--------- Begin of function Nation::update_ai_region --------//
218
update_ai_region()219 void Nation::update_ai_region()
220 {
221 Town* townPtr;
222 int regionRecno;
223
224 memset( ai_region_array, 0, sizeof(ai_region_array) );
225 ai_region_count = 0;
226
227 for( int i=0 ; i<ai_town_count ; i++ )
228 {
229 townPtr = town_array[ ai_town_array[i] ];
230
231 //---- see if this region has been included -------//
232
233 regionRecno=0;
234
235 for( int j=0 ; j<ai_region_count ; j++ )
236 {
237 if( ai_region_array[j].region_id == townPtr->region_id )
238 {
239 regionRecno = j+1;
240 break;
241 }
242 }
243
244 if( !regionRecno ) // not included yet
245 {
246 if( ai_region_count == MAX_AI_REGION ) // no space for adding new region
247 continue;
248
249 err_when( ai_region_count > MAX_AI_REGION );
250
251 ai_region_array[ai_region_count++].region_id = townPtr->region_id;
252
253 regionRecno = ai_region_count;
254 }
255
256 //--- increase the town and base_town_count of the nation ---//
257
258 ai_region_array[regionRecno-1].town_count++;
259
260 if( townPtr->is_base_town )
261 ai_region_array[regionRecno-1].base_town_count++;
262 }
263 }
264 //---------- End of function Nation::update_ai_region --------//
265
266
267 //--------- Begin of function Nation::add_town_info --------//
268
add_town_info(short townRecno)269 void Nation::add_town_info(short townRecno)
270 {
271 update_ai_array(ai_town_count, ai_town_size, &ai_town_array,
272 AI_TOWN_INC_SIZE, 1, townRecno);
273
274 update_ai_region();
275 }
276 //---------- End of function Nation::add_town_info --------//
277
278
279 //--------- Begin of function Nation::del_town_info --------//
280
del_town_info(short townRecno)281 void Nation::del_town_info(short townRecno)
282 {
283 err_when( ai_base_town_count<0 );
284
285 //--- if this is a base town, decrease the base town counter ---//
286
287 if( town_array[townRecno]->is_base_town )
288 {
289 ai_base_town_count--;
290 err_when( ai_base_town_count<0 );
291 }
292
293 //------- delete the record from ai_town_array ------//
294
295 update_ai_array(ai_town_count, ai_town_size, &ai_town_array,
296 AI_TOWN_INC_SIZE, -1, townRecno);
297
298 update_ai_region();
299 }
300 //---------- End of function Nation::del_town_info --------//
301
302
303 //--------- Begin of function Nation::add_general_info --------//
304
add_general_info(short unitRecno)305 void Nation::add_general_info(short unitRecno)
306 {
307 Unit* unitPtr = unit_array[unitRecno];
308
309 err_when( unitPtr->rank_id != RANK_KING && unitPtr->rank_id != RANK_GENERAL );
310
311 update_ai_array(ai_general_count, ai_general_size,
312 &ai_general_array, AI_GENERAL_INC_SIZE, 1, unitRecno);
313 }
314 //---------- End of function Nation::add_general_info --------//
315
316
317 //--------- Begin of function Nation::del_general_info --------//
318
del_general_info(short unitRecno)319 void Nation::del_general_info(short unitRecno)
320 {
321 Unit* unitPtr = unit_array[unitRecno];
322
323 err_when( unitPtr->rank_id != RANK_KING && unitPtr->rank_id != RANK_GENERAL );
324
325 update_ai_array(ai_general_count, ai_general_size,
326 &ai_general_array, AI_GENERAL_INC_SIZE, -1, unitRecno);
327 }
328 //---------- End of function Nation::del_general_info --------//
329
330
331 //--------- Begin of function Nation::add_caravan_info --------//
332
add_caravan_info(short unitRecno)333 void Nation::add_caravan_info(short unitRecno)
334 {
335 update_ai_array(ai_caravan_count, ai_caravan_size, &ai_caravan_array,
336 AI_CARAVAN_INC_SIZE, 1, unitRecno);
337 }
338 //---------- End of function Nation::add_caravan_info --------//
339
340
341 //--------- Begin of function Nation::del_caravan_info --------//
342
del_caravan_info(short unitRecno)343 void Nation::del_caravan_info(short unitRecno)
344 {
345 update_ai_array(ai_caravan_count, ai_caravan_size, &ai_caravan_array,
346 AI_CARAVAN_INC_SIZE, -1, unitRecno);
347 }
348 //---------- End of function Nation::del_caravan_info --------//
349
350
351 //--------- Begin of function Nation::is_caravan_exist --------//
352 //
353 // Check whether there is an existing caravan travelling along
354 // the specific route.
355 //
356 // <int> firstStop, secondStop - firm recno of the first and second stops.
357 // [int] setStopInterval - if this is given, then only caravans
358 // that have been set stop within the given
359 // days will be counted as existing ones.
360 //
is_caravan_exist(int firstStop,int secondStop,int setStopInterval)361 int Nation::is_caravan_exist(int firstStop, int secondStop, int setStopInterval)
362 {
363 UnitCaravan* unitCaravan;
364
365 for( int i=0; i<ai_caravan_count; i++ )
366 {
367 unitCaravan = (UnitCaravan*) unit_array[ ai_caravan_array[i] ];
368
369 if( ( unitCaravan->stop_array[0].firm_recno == firstStop &&
370 unitCaravan->stop_array[1].firm_recno == secondStop ) ||
371 ( unitCaravan->stop_array[1].firm_recno == firstStop &&
372 unitCaravan->stop_array[0].firm_recno == secondStop ) )
373 {
374 if( setStopInterval )
375 {
376 if( info.game_date - unitCaravan->last_set_stop_date < setStopInterval )
377 return unitCaravan->sprite_recno;
378 }
379 else
380 return unitCaravan->sprite_recno;
381 }
382 }
383
384 return 0;
385 }
386 //---------- End of function Nation::is_caravan_exist --------//
387
388
389 //--------- Begin of function Nation::add_ship_info --------//
390
add_ship_info(short unitRecno)391 void Nation::add_ship_info(short unitRecno)
392 {
393 update_ai_array(ai_ship_count, ai_ship_size, &ai_ship_array,
394 AI_SHIP_INC_SIZE, 1, unitRecno);
395 }
396 //---------- End of function Nation::add_ship_info --------//
397
398
399 //--------- Begin of function Nation::del_ship_info --------//
400
del_ship_info(short unitRecno)401 void Nation::del_ship_info(short unitRecno)
402 {
403 update_ai_array(ai_ship_count, ai_ship_size, &ai_ship_array,
404 AI_SHIP_INC_SIZE, -1, unitRecno);
405 }
406 //---------- End of function Nation::del_ship_info --------//
407
408
409 //--------- Begin of function Nation::has_base_town_in_region --------//
410 //
411 // Return whether this nation has any base town in the given region.
412 //
has_base_town_in_region(int regionId)413 int Nation::has_base_town_in_region(int regionId)
414 {
415 for( int i=0 ; i<ai_region_count ; i++ )
416 {
417 if( ai_region_array[i].region_id == regionId )
418 return ai_region_array[i].base_town_count > 0;
419 }
420
421 return 0;
422 }
423 //---------- End of function Nation::has_base_town_in_region --------//
424
425
426 //--------- Begin of function Nation::get_ai_region --------//
427 //
428 // Return the AIRegion of the given region id.
429 //
get_ai_region(int regionId)430 AIRegion* Nation::get_ai_region(int regionId)
431 {
432 for( int i=0 ; i<ai_region_count ; i++ )
433 {
434 if( ai_region_array[i].region_id == regionId )
435 return ai_region_array+i;
436 }
437
438 return 0;
439 }
440 //---------- End of function Nation::get_ai_region --------//
441
442