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 : OU_CARA2.CPP
22 //Description : Unit Caravan - AI functions
23
24 #include <OINFO.h>
25 #include <ONATION.h>
26 #include <OF_FACT.h>
27 #include <OU_CARA.h>
28
29
30 //------- Begin of function UnitCaravan::init_derived --------//
31
init_derived()32 void UnitCaravan::init_derived()
33 {
34 last_load_goods_date = info.game_date;
35 }
36 //------- End of function UnitCaravan::init_derived --------//
37
38
39 //------- Begin of function UnitCaravan::process_ai --------//
40 //
process_ai()41 void UnitCaravan::process_ai()
42 {
43 //-- Think about removing stops whose owner nation is at war with us. --//
44
45 if( info.game_date%30 == sprite_recno%30 )
46 {
47 if( think_del_stop() )
48 return;
49
50 //------ think about setting pickup goods type -----//
51
52 think_set_pick_up_type();
53 }
54
55 //------ Think about resigning this caravan -------//
56
57 think_resign();
58 }
59 //------- End of function UnitCaravan::process_ai --------//
60
61
62 //------- Begin of function UnitCaravan::think_resign --------//
63
think_resign()64 int UnitCaravan::think_resign()
65 {
66 if( !is_visible() ) // can only resign when the caravan is not in a stop
67 return 0;
68
69 //---- resign this caravan if it has only one stop ----//
70
71 if( stop_defined_num < 2 )
72 {
73 resign(COMMAND_AI);
74 return 1;
75 }
76
77 //---- if the caravan hasn't loaded any goods for a year ----//
78
79 if( info.game_date > last_load_goods_date + 365 &&
80 info.game_date%30 == sprite_recno%30 ) // don't call too often as the action may fail and it takes a while to call the function each time
81 {
82 //--- don't resign if this caravan carries any goods ---//
83
84 for( int i=0 ; i<MAX_RAW ; i++ )
85 {
86 if( raw_qty_array[i] > 0 || product_raw_qty_array[i] > 0 )
87 return 0;
88 }
89
90 //------ resign now --------//
91
92 resign(COMMAND_AI);
93 return 1;
94 }
95
96 //--- if this caravan is travelling between two retail markets ---//
97 //--- (neither of them has any direct supplies) ------//
98
99 if( info.game_date%30 == sprite_recno%30 ) // don't call too often as the action may fail and it takes a while to call the function each time
100 {
101 for( int i=stop_defined_num ; i>0 ; i-- )
102 {
103 int firmRecno = stop_array[i-1].firm_recno;
104
105 if( firm_array.is_deleted(firmRecno) ||
106 firm_array[firmRecno]->firm_id != FIRM_MARKET )
107 {
108 del_stop(i, COMMAND_AI);
109 return 1;
110 }
111
112 //--- see if this market has any direct supply ---//
113
114 FirmMarket* firmMarket = (FirmMarket*) firm_array[firmRecno];
115
116 MarketGoods* marketGoods = firmMarket->market_goods_array;
117
118 for( int j=0 ; j<MAX_MARKET_GOODS ; j++, marketGoods++ )
119 {
120 if( marketGoods->supply_30days() > 0 )
121 return 0;
122 }
123 }
124
125 //--- resign now if none of the linked markets have any direct supplies ---//
126
127 resign(COMMAND_AI);
128 return 1;
129 }
130
131 return 0;
132 }
133 //------- End of function UnitCaravan::think_resign --------//
134
135
136 //------- Begin of function UnitCaravan::think_del_stop --------//
137 //
138 // Think about removing stops whose owner nation is at war with us.
139 //
think_del_stop()140 int UnitCaravan::think_del_stop()
141 {
142 if( !is_visible() ) // cannot del stop if the caravan is inside a market place.
143 return 0;
144
145 Firm* firmPtr;
146 Nation* nationPtr = nation_array[nation_recno];
147
148 int i;
149 for( i=stop_defined_num ; i>0 ; i-- )
150 {
151 int firmRecno = stop_array[i-1].firm_recno;
152
153 if( firm_array.is_deleted(firmRecno) )
154 {
155 del_stop(i, COMMAND_AI);
156 return 1;
157 }
158
159 //---- AI only knows how to trade from a market to another ------//
160
161 firmPtr = firm_array[firmRecno];
162
163 if( firmPtr->firm_id != FIRM_MARKET ||
164 nationPtr->get_relation(firmPtr->nation_recno)->trade_treaty==0 ) // if the treaty trade has been terminated, delete the stop
165 {
166 del_stop(i, COMMAND_AI);
167 return 1;
168 }
169
170 //--- If this market is not linked to any towns ---//
171
172 FirmMarket* firmMarket = (FirmMarket*) firm_array[stop_array[i-1].firm_recno];
173
174 if( !firmMarket->is_market_linked_to_town() )
175 {
176 //--- and the caravan is not currently picking up goods from the market ---//
177
178 int hasPickUp=0;
179 TradeStop* tradeStop = stop_array + i - 1;
180
181 int j;
182 for( j=PICK_UP_RAW_FIRST ; j<=PICK_UP_RAW_LAST ; j++ )
183 {
184 if( tradeStop->pick_up_array[j] )
185 hasPickUp = 1;
186 }
187
188 for( j=PICK_UP_PRODUCT_FIRST ; j<=PICK_UP_PRODUCT_LAST ; j++ )
189 {
190 if( tradeStop->pick_up_array[j] )
191 hasPickUp = 1;
192 }
193
194 //---- then delete the stop -----//
195
196 if( !hasPickUp )
197 {
198 del_stop(i, COMMAND_AI);
199 return 1;
200 }
201 }
202
203 //----------------------------------------------//
204
205 int nationRecno = firmMarket->nation_recno;
206
207 if( nationPtr->get_relation_status(nationRecno) == NATION_HOSTILE )
208 {
209 del_stop(i, COMMAND_AI);
210 return 1;
211 }
212 }
213
214 //----------- debug code ----------//
215
216 #ifdef DEBUG
217 for( i=stop_defined_num ; i>0 ; i-- )
218 {
219 err_when( firm_array.is_deleted(stop_array[i-1].firm_recno) );
220 }
221 #endif
222
223 return 0;
224 }
225 //------- End of function UnitCaravan::think_del_stop --------//
226
227
228 //------- Begin of function UnitCaravan::think_set_pick_up_type --------//
229 //
230 // Think about setting the pick up types of this caravan's stops.
231 //
think_set_pick_up_type()232 void UnitCaravan::think_set_pick_up_type()
233 {
234 if( !is_visible() ) // cannot change pickup type if the caravan is inside a market place.
235 return;
236
237 if( stop_defined_num < 2 )
238 return;
239
240 //------------------------------------------//
241
242 err_when( firm_array.is_deleted(stop_array[0].firm_recno) );
243 err_when( firm_array.is_deleted(stop_array[1].firm_recno) );
244
245 Firm* firmPtr1 = firm_array[stop_array[0].firm_recno];
246 Firm* firmPtr2 = firm_array[stop_array[1].firm_recno];
247
248 if( firmPtr1->firm_id != FIRM_MARKET || // only when both firms are markets
249 firmPtr2->firm_id != FIRM_MARKET )
250 {
251 return;
252 }
253
254 if( firmPtr2->nation_recno == nation_recno && // only when the market is our own, we can use it as a TO market
255 ((FirmMarket*)firmPtr2)->is_retail_market )
256 {
257 think_set_pick_up_type2( 1, 2 );
258 }
259
260 if( firmPtr1->nation_recno == nation_recno &&
261 ((FirmMarket*)firmPtr1)->is_retail_market )
262 {
263 think_set_pick_up_type2( 2, 1 );
264 }
265 }
266 //------- End of function UnitCaravan::think_set_pick_up_type --------//
267
268
269 //------- Begin of function UnitCaravan::think_set_pick_up_type2 --------//
270 //
271 // Think about importing products from one firm to another
272 //
think_set_pick_up_type2(int fromStopId,int toStopId)273 void UnitCaravan::think_set_pick_up_type2(int fromStopId, int toStopId)
274 {
275 FirmMarket* fromMarket = (FirmMarket*) firm_array[stop_array[fromStopId-1].firm_recno];
276 FirmMarket* toMarket = (FirmMarket*) firm_array[stop_array[toStopId-1].firm_recno];
277
278 //----- AI only knows about market to market trade -----//
279
280 if( fromMarket->firm_id != FIRM_MARKET || toMarket->firm_id != FIRM_MARKET )
281 return;
282
283 //---- think about adding new pick up types -----//
284
285 MarketGoods* marketGoods = fromMarket->market_goods_array;
286 TradeStop* tradeStop = stop_array+fromStopId-1;
287
288 int i;
289 for( i=0 ; i<MAX_MARKET_GOODS ; i++, marketGoods++ )
290 {
291 if( !marketGoods->product_raw_id )
292 continue;
293
294 //----- only if this market has direct supplies -----//
295
296 if( marketGoods->supply_30days()==0 )
297 continue;
298
299 //-- when the from market has the product and the to market does not have the product, then trade this good --//
300
301 int pickUpType = PICK_UP_PRODUCT_FIRST+marketGoods->product_raw_id-1;
302
303 //------ toggle it if the current flag and the flag we need are different ----//
304
305 if( !tradeStop->pick_up_array[pickUpType-1] )
306 set_stop_pick_up(fromStopId, pickUpType, COMMAND_AI);
307 }
308
309 //---- think about droping existing pick up types -----//
310
311 for( i=PICK_UP_RAW_FIRST ; i<=PICK_UP_RAW_LAST ; i++ )
312 {
313 if( !tradeStop->pick_up_array[i-1] )
314 continue;
315
316 marketGoods = fromMarket->market_raw_array[i-PICK_UP_RAW_FIRST];
317
318 //----- if there is no supply, drop the pick up type -----//
319
320 if( !marketGoods || marketGoods->supply_30days() == 0 )
321 set_stop_pick_up(fromStopId, i, COMMAND_AI);
322 }
323
324 for( i=PICK_UP_PRODUCT_FIRST ; i<=PICK_UP_PRODUCT_LAST ; i++ )
325 {
326 if( !tradeStop->pick_up_array[i-1] )
327 continue;
328
329 marketGoods = fromMarket->market_product_array[i-PICK_UP_PRODUCT_FIRST];
330
331 //--- if the supply is not enough, drop the pick up type ---//
332
333 if( !marketGoods || marketGoods->supply_30days()==0 )
334 set_stop_pick_up(fromStopId, i, COMMAND_AI);
335 }
336 }
337 //------- End of function UnitCaravan::think_set_pick_up_type2 --------//
338
339