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_CARA3.CPP
22 //Description : Unit Caravan unload/load functions
23
24 #include <ONATION.h>
25 #include <OF_MINE.h>
26 #include <OF_FACT.h>
27 #include <OF_MARK.h>
28 #include <OU_CARA.h>
29 #include <OREMOTE.h>
30
31 static char processed_raw_qty_array[MAX_RAW]; // 1 for not unload but can up load, 2 for unload but not up load
32 static char processed_product_raw_qty_array[MAX_PRODUCT]; // ditto
33
34 //--------- Begin of function UnitCaravan::market_unload_goods ---------//
35 //
market_unload_goods()36 void UnitCaravan::market_unload_goods()
37 {
38 FirmMarket *curMarket = (FirmMarket*) firm_array[stop_array[dest_stop_id-1].firm_recno];
39 err_when(curMarket->firm_id != FIRM_MARKET);
40
41 memset(processed_raw_qty_array, 0, sizeof(char)*MAX_RAW);
42 memset(processed_product_raw_qty_array, 0, sizeof(char)*MAX_PRODUCT);
43
44 //--------------------------------------------------------------------//
45 // only unload goods to our market
46 //--------------------------------------------------------------------//
47 if(curMarket->nation_recno!=nation_recno)
48 return;
49
50 //--------------------------------------------------------------------//
51 // unload goods
52 //-------------------------------------------------//
53 MarketGoods *marketGoods = curMarket->market_goods_array;
54 short unloadQty;
55 int goodsId, withEmptySlot=0;
56
57 int i;
58 for(i=0; i<MAX_MARKET_GOODS; i++, marketGoods++)
59 {
60 if(marketGoods->raw_id)
61 {
62 err_when(marketGoods->product_raw_id);
63 //-------------- is raw material ----------------//
64 goodsId = marketGoods->raw_id-1;
65
66 //if( (marketGoods->supply_30days()==0 && marketGoods->stock_qty<curMarket->max_stock_qty) || // no supply and stock isn't full
67 // (marketGoods->stock_qty<CARAVAN_UNLOAD_TO_MARKET_QTY &&
68 // //##### begin trevor 16/7 #######//
69 // marketGoods->month_demand > marketGoods->supply_30days()) ) // demand > supply
70 // //##### end trevor 16/7 #######//
71 if(marketGoods->stock_qty<curMarket->max_stock_qty)
72 {
73 //-------- demand > supply and stock is not full ----------//
74 if(raw_qty_array[goodsId]) // have this goods
75 {
76 //---------- process unload -------------//
77 unloadQty = (short) MIN(raw_qty_array[goodsId], curMarket->max_stock_qty-marketGoods->stock_qty);
78 raw_qty_array[goodsId] -= unloadQty;
79 err_when(raw_qty_array[goodsId]<0);
80 marketGoods->stock_qty += unloadQty;
81 processed_raw_qty_array[goodsId] += 2;
82 }
83 else if(!marketGoods->stock_qty && !marketGoods->supply_30days())
84 {
85 //---------- no supply, no stock, without this goods ------------//
86 withEmptySlot++;
87 //processed_raw_qty_array[goodsId] = 0; // reset to zero for handling empty slot
88 }
89 }
90 else if(raw_qty_array[goodsId]) // have this goods
91 {
92 processed_raw_qty_array[goodsId]++;
93 }
94 }
95 else if(marketGoods->product_raw_id)
96 {
97 err_when(marketGoods->raw_id);
98 //---------------- is product -------------------//
99 goodsId = marketGoods->product_raw_id-1;
100
101 //if( (marketGoods->supply_30days()==0 && marketGoods->stock_qty<curMarket->max_stock_qty) || // no supply and stock isn't full
102 // //##### begin trevor 16/7 #######//
103 // (marketGoods->stock_qty<50 && marketGoods->month_demand > marketGoods->supply_30days()) ) // demand > supply
104 // //##### end trevor 16/7 #######//
105 if(marketGoods->stock_qty<curMarket->max_stock_qty)
106 {
107 if(product_raw_qty_array[goodsId]) // have this goods
108 {
109 unloadQty = (short) MIN(product_raw_qty_array[goodsId], curMarket->max_stock_qty-marketGoods->stock_qty);
110 product_raw_qty_array[goodsId] -= unloadQty;
111 err_when(product_raw_qty_array[goodsId]<0);
112 marketGoods->stock_qty += unloadQty;
113 processed_product_raw_qty_array[goodsId] += 2;
114 }
115 else if(!marketGoods->stock_qty && !marketGoods->supply_30days()) // no supply, no stock, without this goods
116 {
117 withEmptySlot++;
118 //processed_product_raw_qty_array[goodsId] = 0; // reset to zero for handling empty slot
119 }
120 }
121 else if(product_raw_qty_array[goodsId]) // have this goods
122 {
123 processed_product_raw_qty_array[goodsId]++;
124 }
125 }
126 else // is empty
127 {
128 if(!market_unload_goods_in_empty_slot(curMarket, i))
129 break; // no goods for further checking
130 }
131 }
132
133 //-------------------------------------------------//
134 // unload new goods in the empty slots
135 //-------------------------------------------------//
136 if(withEmptySlot)
137 {
138 marketGoods = curMarket->market_goods_array;
139 for(i=0; i<MAX_MARKET_GOODS && withEmptySlot; i++, marketGoods++)
140 {
141 if(marketGoods->stock_qty || marketGoods->supply_30days())
142 continue;
143
144 market_unload_goods_in_empty_slot(curMarket, i);
145 withEmptySlot--;
146 }
147 }
148
149 err_when(withEmptySlot);
150 }
151 //----------- End of function UnitCaravan::market_unload_goods -----------//
152
153
154 //--------- Begin of function UnitCaravan::market_unload_goods_in_empty_slot ---------//
155 //
156 // This function searches for possible new product or raw material to unload
157 // to a provided empty market slot. It will favor refined product first, then
158 // raw material.
159 //
160 // return 0 if no goods are unloaded and there are no other goods to unload
161 // to a different slot
162 // return 1 if goods are unloaded or there are other goods to unload to a
163 // different slot
164 //
market_unload_goods_in_empty_slot(FirmMarket * curMarket,int position)165 int UnitCaravan::market_unload_goods_in_empty_slot(FirmMarket *curMarket, int position)
166 {
167 int more_to_unload = 0;
168 MarketGoods* marketGoods = curMarket->market_goods_array + position;
169
170 //-------------------------------------------------//
171 // unload product and then raw
172 //-------------------------------------------------//
173 int processed, j;
174 for(processed=0, j=0; j<MAX_PRODUCT; j++)
175 {
176 MarketGoods *checkGoods;
177 int productExistInOtherSlot;
178
179 if(processed_product_raw_qty_array[j] || !product_raw_qty_array[j])
180 continue; // this product is processed or no stock in the caravan
181
182 // this can be unloaded, but check if it can be
183 // unloaded into an already provided market slot
184 // for this product type
185
186 checkGoods = curMarket->market_goods_array;
187 productExistInOtherSlot = 0;
188 for(int k=0; k<MAX_MARKET_GOODS; k++, checkGoods++)
189 {
190 if(checkGoods->product_raw_id==j+1)
191 {
192 productExistInOtherSlot++;
193 break;
194 }
195 }
196
197 if(productExistInOtherSlot)
198 {
199 more_to_unload++;
200 continue;
201 }
202
203 // this does not exist in a market slot, so unload
204 // in this empty one
205
206 #ifdef DEBUG
207 MarketGoods *debugGoods = curMarket->market_goods_array;
208 for(int debugCount=0; debugCount<MAX_MARKET_GOODS; ++debugCount, debugGoods++)
209 err_when(debugGoods->product_raw_id==j+1);
210 #endif
211
212 //-**************************************************-//
213 //err_when(marketGoods->stock_qty);
214 marketGoods->stock_qty = (float) 0; // BUGHERE, there is a case that marketGoods->stock_qty > 0
215 //-**************************************************-//
216 processed_product_raw_qty_array[j] += 2;
217 curMarket->set_goods(0, j+1, position);
218
219 short unloadQty = (short) MIN(product_raw_qty_array[j], curMarket->max_stock_qty-marketGoods->stock_qty);
220 product_raw_qty_array[j] -= unloadQty;
221 marketGoods->stock_qty += unloadQty;
222 processed++;
223 break;
224 }
225
226 if(!processed)
227 {
228 for(j=0; j<MAX_PRODUCT; j++)
229 {
230 MarketGoods *checkGoods;
231 int rawExistInOtherSlot;
232 if(processed_raw_qty_array[j] || !raw_qty_array[j])
233 continue; // this product is processed or no stock in the caravan
234
235 // this can be unloaded, but check if it can be
236 // unloaded into an already provided market slot
237 // for this product type
238
239 checkGoods = curMarket->market_goods_array;
240 rawExistInOtherSlot = 0;
241 for(int k=0; k<MAX_MARKET_GOODS; k++, checkGoods++)
242 {
243 if(checkGoods->raw_id==j+1)
244 {
245 rawExistInOtherSlot++;
246 break;
247 }
248 }
249
250 if(rawExistInOtherSlot)
251 {
252 more_to_unload++;
253 continue;
254 }
255
256 // this does not exist in a market slot, so unload
257 // in this empty one
258
259 #ifdef DEBUG
260 MarketGoods *debugGoods = curMarket->market_goods_array;
261 for(int debugCount=0; debugCount<MAX_MARKET_GOODS; ++debugCount, debugGoods++)
262 err_when(debugGoods->raw_id==j+1);
263 #endif
264
265 //-**************************************************-//
266 //err_when(marketGoods->stock_qty);
267 marketGoods->stock_qty = (float) 0; // BUGHERE, there is a case that marketGoods->stock_qty > 0
268 //-**************************************************-//
269 processed_raw_qty_array[j] += 2;
270 curMarket->set_goods(1, j+1, position);
271
272 short unloadQty = (short) MIN(raw_qty_array[j], curMarket->max_stock_qty-marketGoods->stock_qty);
273 raw_qty_array[j] -= unloadQty;
274 marketGoods->stock_qty += unloadQty;
275 processed++;
276 break;
277 }
278 }
279
280 if( unit_array.selected_recno == sprite_recno )
281 info.disp();
282
283 return (processed || more_to_unload);
284 }
285 //----------- End of function UnitCaravan::market_unload_goods_in_empty_slot -----------//
286
287
288 //--------- Begin of function UnitCaravan::market_load_goods ---------//
289 //
market_load_goods()290 void UnitCaravan::market_load_goods()
291 {
292 CaravanStop *stopPtr = stop_array+dest_stop_id-1;
293 err_when(stopPtr->pick_up_type == NO_PICK_UP);
294
295 FirmMarket *curMarket = (FirmMarket*) firm_array[ stopPtr->firm_recno ];
296 err_when(curMarket->firm_id != FIRM_MARKET);
297 MarketGoods *marketGoods=curMarket->market_goods_array;
298
299 //------------------------------------------------------------//
300 // scan the market, see if it has the specified pickup goods
301 //------------------------------------------------------------//
302 for(int i=0; i<MAX_MARKET_GOODS; i++, marketGoods++)
303 {
304 if(marketGoods->raw_id)
305 {
306 if(stopPtr->pick_up_array[marketGoods->raw_id-1])
307 market_load_goods_now(marketGoods, marketGoods->stock_qty);
308 }
309 else if(marketGoods->product_raw_id)
310 {
311 if(stopPtr->pick_up_array[marketGoods->product_raw_id-1+MAX_RAW])
312 market_load_goods_now(marketGoods, marketGoods->stock_qty);
313 }
314 }
315 }
316 //----------- End of function UnitCaravan::market_load_goods -----------//
317
318
319 //--------- Begin of function UnitCaravan::market_auto_load_goods ---------//
320 //
market_auto_load_goods()321 void UnitCaravan::market_auto_load_goods()
322 {
323 FirmMarket *curMarket = (FirmMarket*) firm_array[ stop_array[dest_stop_id-1].firm_recno ];
324 err_when(curMarket->firm_id != FIRM_MARKET);
325
326 MarketGoods *marketGoods = curMarket->market_goods_array;
327 //int isOurMarket = (curMarket->nation_recno==nation_recno); // is 1 or 0
328 int goodsId;
329 short loadQty;
330
331 //----------------------------------------------------------------------//
332 // keep empty stock if the market(AI) is for sale, otherwise use the
333 // default value
334 //----------------------------------------------------------------------//
335 //short minFirmStockQty = (int)curMarket->max_stock_qty/5; // keep at least 20% capacity in the firm if the market is not for sale
336
337 for(int i=0; i<MAX_MARKET_GOODS; i++, marketGoods++)
338 {
339 if(!marketGoods->stock_qty)
340 continue;
341
342 if(marketGoods->raw_id)
343 {
344 err_when(marketGoods->product_raw_id);
345 (goodsId = marketGoods->raw_id)--;
346 if(processed_raw_qty_array[goodsId]==2)
347 continue; // continue if it is the goods unloaded
348
349 if(marketGoods->stock_qty > MIN_FIRM_STOCK_QTY)
350 {
351 loadQty = (short) (marketGoods->stock_qty - MIN_FIRM_STOCK_QTY);
352 err_when(loadQty<0);
353 market_load_goods_now(marketGoods, (float) loadQty);
354 }
355 }
356 //else if(marketGoods->product_raw_id && isOurMarket) // only load product in our market
357 else if(marketGoods->product_raw_id)
358 {
359 err_when(marketGoods->raw_id);
360 (goodsId = marketGoods->product_raw_id)--;
361 if(processed_product_raw_qty_array[goodsId]==2)
362 continue; // continue if it is the goods unloaded
363
364 if(marketGoods->stock_qty > MIN_FIRM_STOCK_QTY)
365 {
366 loadQty = (short) (marketGoods->stock_qty - MIN_FIRM_STOCK_QTY);
367 err_when(loadQty<0);
368 market_load_goods_now(marketGoods, (float) loadQty);
369 }
370 }
371 }
372 }
373 //----------- End of function UnitCaravan::market_auto_load_goods -----------//
374
375
376 //--------- Begin of function UnitCaravan::market_load_goods_now ---------//
377 //
market_load_goods_now(MarketGoods * marketGoods,float loadQty)378 void UnitCaravan::market_load_goods_now(MarketGoods* marketGoods, float loadQty)
379 {
380 Nation *nationPtr = nation_array[nation_recno];
381 int marketNationRecno = firm_array[stop_array[dest_stop_id-1].firm_recno]->nation_recno;
382 short qty;
383 int goodsId;
384
385 if(marketGoods->product_raw_id)
386 {
387 //---------------- is product ------------------//
388 err_when(marketGoods->raw_id);
389 (goodsId = marketGoods->product_raw_id)--;
390
391 qty = MIN(MAX_CARAVAN_CARRY_QTY-product_raw_qty_array[goodsId], (int)loadQty);
392 if(marketNationRecno!=nation_recno) // calculate the qty again if this is not our own market
393 {
394 qty = (nationPtr->cash>0) ? (short) MIN(nationPtr->cash/PRODUCT_PRICE, qty) : 0;
395
396 if(qty)
397 nationPtr->import_goods(IMPORT_PRODUCT, marketNationRecno, (float)qty * PRODUCT_PRICE);
398 }
399
400 product_raw_qty_array[goodsId] += qty;
401 err_when(product_raw_qty_array[goodsId]<0 || product_raw_qty_array[goodsId]>MAX_CARAVAN_CARRY_QTY);
402 marketGoods->stock_qty -= qty;
403 }
404 else if(marketGoods->raw_id)
405 {
406 //---------------- is raw ---------------------//
407 err_when(marketGoods->product_raw_id);
408 (goodsId = marketGoods->raw_id)--;
409
410 qty = MIN(MAX_CARAVAN_CARRY_QTY-raw_qty_array[goodsId], (int)loadQty);
411 if(marketNationRecno!=nation_recno) // calculate the qty again if this is not our own market
412 {
413 qty = (nationPtr->cash>0) ? (short) MIN(nationPtr->cash/RAW_PRICE, qty) : 0;
414
415 if(qty)
416 nationPtr->import_goods(IMPORT_RAW, marketNationRecno, (float)qty * RAW_PRICE);
417 }
418
419 raw_qty_array[goodsId] += qty;
420 err_when(raw_qty_array[goodsId]<0 || raw_qty_array[goodsId]>MAX_CARAVAN_CARRY_QTY);
421 marketGoods->stock_qty -= qty;
422 }
423
424 //### begin trevor 7/8 ###//
425
426 if( qty > 0 )
427 last_load_goods_date = info.game_date;
428
429 //#### end trevor 7/8 ####//
430 }
431 //----------- End of function UnitCaravan::market_load_goods_now -----------//
432
433
434 //--------- Begin of function UnitCaravan::mine_load_goods ---------//
mine_load_goods(char pickUpType)435 void UnitCaravan::mine_load_goods(char pickUpType)
436 {
437 if(pickUpType == NO_PICK_UP)
438 return; // return if not allowed to load any goods
439
440 err_when(pickUpType>=PICK_UP_PRODUCT_FIRST && pickUpType<=PICK_UP_PRODUCT_LAST);
441 CaravanStop *stopPtr = stop_array+dest_stop_id-1;
442 FirmMine *curMine = (FirmMine*) firm_array[stopPtr->firm_recno];
443 err_when(curMine->firm_id != FIRM_MINE);
444
445 if(curMine->nation_recno!=nation_recno)
446 return; // no action if this is not our own mine
447
448 //------------- load goods -----------//
449 int searchRawId = pickUpType-PICK_UP_RAW_FIRST+1;
450 if(pickUpType==AUTO_PICK_UP || curMine->raw_id==searchRawId) // auto_pick_up or is the raw to pick up
451 {
452 int goodsId = curMine->raw_id-1;
453 short maxLoadQty = (pickUpType!=AUTO_PICK_UP) ? (short)curMine->stock_qty :
454 MAX(0, (int)(curMine->stock_qty-MIN_FIRM_STOCK_QTY)); // MAX Qty mine can supply
455 err_when(goodsId >= MAX_RAW);
456 short qty = MIN(MAX_CARAVAN_CARRY_QTY-raw_qty_array[goodsId], maxLoadQty); // MAX Qty caravan can carry
457
458 raw_qty_array[goodsId] += qty;
459 err_when(raw_qty_array[goodsId]<0 || raw_qty_array[goodsId]>MAX_CARAVAN_CARRY_QTY);
460 curMine->stock_qty -= qty;
461
462 //### begin trevor 7/8 ####//
463
464 if( maxLoadQty > 0 )
465 last_load_goods_date = info.game_date;
466
467 //#### end trevor 7/8 ####//
468 }
469 }
470 //----------- End of function UnitCaravan::mine_load_goods -----------//
471
472
473 //--------- Begin of function UnitCaravan::factory_unload_goods ---------//
474 // unload raw material to factory
475 //
factory_unload_goods()476 void UnitCaravan::factory_unload_goods()
477 {
478 CaravanStop *stopPtr = stop_array+dest_stop_id-1;
479 FirmFactory *curFactory = (FirmFactory*) firm_array[stopPtr->firm_recno];
480 err_when(curFactory->firm_id != FIRM_FACTORY);
481
482 if(curFactory->nation_recno!=nation_recno)
483 return; // don't unload goods if this isn't our own factory
484
485 //--- if the factory does not have any stock and there is no production, set it to type of raw materials the caravan is carring ---//
486
487 if( curFactory->stock_qty == 0 &&
488 curFactory->raw_stock_qty == 0 &&
489 curFactory->production_30days() == 0 )
490 {
491 int rawCount=0;
492 int rawId=0;
493
494 for( int i=0 ; i<MAX_RAW ; i++ )
495 {
496 if( raw_qty_array[i] > 0 )
497 {
498 rawCount++;
499 rawId=i+1;
500 }
501 }
502
503 //-- only if the caravan only carries one type of raw material --//
504
505 if( rawCount==1 && rawId )
506 curFactory->product_raw_id = rawId;
507 }
508
509 //---------- unload materials automatically --------//
510 int goodsId = curFactory->product_raw_id-1;
511
512 if(raw_qty_array[goodsId]) // caravan has this raw materials
513 {
514 short qty = MIN(raw_qty_array[goodsId], (short)(curFactory->max_raw_stock_qty-curFactory->raw_stock_qty));
515 raw_qty_array[goodsId] -= qty;
516 err_when(raw_qty_array[goodsId]<0);
517 curFactory->raw_stock_qty += qty;
518 err_when(curFactory->raw_stock_qty>curFactory->max_raw_stock_qty);
519 }
520 }
521 //----------- End of function UnitCaravan::factory_unload_goods -----------//
522
523
524 //--------- Begin of function UnitCaravan::factory_load_goods ---------//
factory_load_goods(char pickUpType)525 void UnitCaravan::factory_load_goods(char pickUpType)
526 {
527 if(pickUpType==NO_PICK_UP)
528 return; // return not allowed to load any goods
529
530 err_when(pickUpType>=PICK_UP_RAW_FIRST && pickUpType<=PICK_UP_RAW_LAST);
531 CaravanStop *stopPtr = stop_array+dest_stop_id-1;
532 FirmFactory *curFactory = (FirmFactory*) firm_array[stopPtr->firm_recno];
533 err_when(curFactory->firm_id != FIRM_FACTORY);
534
535 if(curFactory->nation_recno!=nation_recno)
536 return; // don't load goods if this isn't our own factory
537
538 //------------- load goods -----------//
539 int searchProductRawId = pickUpType-PICK_UP_PRODUCT_FIRST+1;
540 if(pickUpType==AUTO_PICK_UP || curFactory->product_raw_id==searchProductRawId) // auto_pick_up or is the product to pick up
541 {
542 int goodsId = curFactory->product_raw_id-1;
543 short maxLoadQty = (pickUpType!=AUTO_PICK_UP) ? (short)curFactory->stock_qty :
544 MAX(0, (int)(curFactory->stock_qty-MIN_FIRM_STOCK_QTY)); // MAX Qty factory can supply
545 err_when(goodsId < 0);
546 short qty = MIN(MAX_CARAVAN_CARRY_QTY-product_raw_qty_array[goodsId], maxLoadQty); // MAX Qty caravan can carry
547
548 product_raw_qty_array[goodsId] += qty;
549 err_when(product_raw_qty_array[goodsId]<0 || product_raw_qty_array[goodsId]>MAX_CARAVAN_CARRY_QTY);
550 curFactory->stock_qty -= qty;
551
552 //### begin trevor 7/8 ####//
553
554 if( maxLoadQty > 0 )
555 last_load_goods_date = info.game_date;
556
557 //#### end trevor 7/8 ####//
558 }
559 }
560 //----------- End of function UnitCaravan::factory_load_goods -----------//
561