/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : OU_MARI3.CPP //Description: UnitMarine - functions for loading/unloading goods, trading #include #include #include #include #include #include #include #include #include static char mprocessed_raw_qty_array[MAX_LINKED_FIRM_FIRM][MAX_RAW]; // 1 for not unload but can up load, 2 for unload but not up load static char mprocessed_product_raw_qty_array[MAX_LINKED_FIRM_FIRM][MAX_PRODUCT]; // ditto static char linked_mine_num; static char linked_factory_num; static char linked_market_num; static short linked_mine_array[MAX_LINKED_FIRM_FIRM]; static short linked_factory_array[MAX_LINKED_FIRM_FIRM]; static short linked_market_array[MAX_LINKED_FIRM_FIRM]; static char empty_slot_position_array[MAX_LINKED_FIRM_FIRM]; static char firm_selected_array[MAX_LINKED_FIRM_FIRM]; //--------- Begin of function UnitMarine::del_stop ---------// void UnitMarine::del_stop(int stopId, char remoteAction) { // ####### begin Gilbert 30/7 #######// if(!remoteAction && remote.is_enable()) { // packet structure : short *shortPtr = (short *) remote.new_send_queue_msg(MSG_U_SHIP_DEL_STOP, 2*sizeof(short)); *shortPtr = sprite_recno; shortPtr[1] = stopId; return; } // ####### end Gilbert 30/7 #######// if(remote.is_enable() && stop_array[stopId-1].firm_recno==0) return; stop_array[stopId-1].firm_recno = 0; stop_defined_num--; update_stop_list(); if(unit_array.selected_recno==sprite_recno) { if(!remote.is_enable() || nation_recno==nation_array.player_recno || config.show_ai_info) info.disp(); } } //---------- End of function UnitMarine::del_stop ----------// //--------- Begin of function UnitMarine::update_stop_list ---------// void UnitMarine::update_stop_list() { //------------- used to debug for multiplayer game ------------------// #ifdef DEBUG m.random(100); #endif //-------------------------------------------------------// // backup original destination stop firm recno //-------------------------------------------------------// err_when(stop_defined_num<0 || stop_defined_num>MAX_STOP_FOR_SHIP); short nextStopRecno = dest_stop_id ? stop_array[dest_stop_id-1].firm_recno : 0; //----------------------------------------------------------------------// // check stop existence and the relationship between firm's nation //----------------------------------------------------------------------// ShipStop *nodePtr = stop_array; Firm *firmPtr; int i; for(i=0; ifirm_recno) continue; if(firm_array.is_deleted(nodePtr->firm_recno)) { nodePtr->firm_recno = 0; // clear the recno stop_defined_num--; continue; } firmPtr = firm_array[nodePtr->firm_recno]; if( !can_set_stop(firmPtr->firm_recno) || firmPtr->loc_x1 != nodePtr->firm_loc_x1 || firmPtr->loc_y1 != nodePtr->firm_loc_y1 ) { nodePtr->firm_recno = 0; stop_defined_num--; continue; } } //-------------------------------------------------------// // remove duplicate node //-------------------------------------------------------// ShipStop *insertNodePtr = stop_array; if(stop_defined_num<1) { memset(stop_array, 0, sizeof(ShipStop)*MAX_STOP_FOR_SHIP); dest_stop_id = 0; return; // no stop } //-------------------------------------------------------// // move the only firm_recno to the beginning of the array //-------------------------------------------------------// short compareRecno; for(i=0, nodePtr=stop_array; ifirm_recno) { compareRecno = nodePtr->firm_recno; break; } } if(i++) // else, the first record is already in the beginning of the array memcpy(insertNodePtr, nodePtr, sizeof(ShipStop)); if(stop_defined_num==1) { memset(insertNodePtr+1, 0, sizeof(ShipStop)*(MAX_STOP_FOR_SHIP-1)); dest_stop_id = 1; return; } short unprocessed = stop_defined_num-1; err_when(i==MAX_STOP_FOR_SHIP); // error if only one record err_when(!unprocessed); insertNodePtr++; nodePtr++; for(; ifirm_recno) continue; // empty err_when(!nodePtr->firm_recno); if(nodePtr->firm_recno==compareRecno) { nodePtr->firm_recno = 0; stop_defined_num--; } else { compareRecno = nodePtr->firm_recno; if(insertNodePtr!=nodePtr) memcpy(insertNodePtr++, nodePtr, sizeof(ShipStop)); else insertNodePtr++; } unprocessed--; } if(stop_defined_num>2) { //-------- compare the first and the end record -------// nodePtr = stop_array + stop_defined_num - 1; // point to the end if(nodePtr->firm_recno == stop_array[0].firm_recno) { nodePtr->firm_recno = 0; // remove the end record stop_defined_num--; } } if(stop_defined_numfirm_recno)); firmPtr = firm_array[nodePtr->firm_recno]; if(firmPtr->nation_recno==nation_recno) { ourFirmExist++; break; } } if(!ourFirmExist) // none of the markets belong to our nation { memset(stop_array, 0, MAX_STOP_FOR_SHIP * sizeof(ShipStop)); journey_status = ON_WAY_TO_FIRM; dest_stop_id = 0; stop_defined_num = 0; return; } //-----------------------------------------------------------------------------------------// // reset dest_stop_id since the order of the stop may be changed //-----------------------------------------------------------------------------------------// int xLoc = next_x_loc(); int yLoc = next_y_loc(); int dist, minDist=0x7FFF; for(i=0, dest_stop_id=0, nodePtr=stop_array; ifirm_recno==nextStopRecno) { dest_stop_id = i+1; break; } else { firmPtr = firm_array[nodePtr->firm_recno]; dist = m.points_distance(xLoc, yLoc, firmPtr->center_x, firmPtr->center_y); if(distMAX_STOP_FOR_SHIP); } //----------- End of function UnitMarine::update_stop_list -----------// //--------- Begin of function UnitMarine::get_next_stop_id ---------// // Get the id. of the next defined stop. // // [int] curStopId - the id. of the current stop. // if it is MAX_STOP_FOR_SHIP, this function will return // the id. of the first valid stop. // // (default: MAX_STOP_FOR_SHIP) // return : 0 ~ MAX_STOP_FOR_SHIP, where 0 for no valid stop // int UnitMarine::get_next_stop_id(int curStopId) { int nextStopId = (curStopId>=stop_defined_num) ? 1 : curStopId+1; ShipStop *stopPtr = stop_array+nextStopId-1; int needUpdate = 0; if(firm_array.is_deleted(stopPtr->firm_recno)) needUpdate++; else { Firm *firmPtr = firm_array[stopPtr->firm_recno]; if( !can_set_stop(firmPtr->firm_recno) || firmPtr->loc_x1 != stopPtr->firm_loc_x1 || firmPtr->loc_y1 != stopPtr->firm_loc_y1 ) { needUpdate++; } } if(needUpdate) { short preStopRecno = stop_array[curStopId-1].firm_recno; update_stop_list(); if(!stop_defined_num) return 0; // no stop is valid int i; for(i=1, stopPtr=stop_array; i<=stop_defined_num; i++, stopPtr++) { if(stopPtr->firm_recno==preStopRecno) nextStopId = (i>=stop_defined_num) ? 1 : i+1; } } return nextStopId; } //----------- End of function UnitMarine::get_next_stop_id -----------// //--------- Begin of function UnitMarine::can_set_stop ---------// // // Whether can set a caravan's stop on the given firm. // int UnitMarine::can_set_stop(int firmRecno) { Firm* firmPtr = firm_array[firmRecno]; if( firmPtr->under_construction ) return 0; if( firmPtr->firm_id != FIRM_HARBOR ) return 0; return nation_array[nation_recno]->get_relation(firmPtr->nation_recno)->trade_treaty; } //----------- End of function UnitMarine::can_set_stop -----------// //--------- Begin of function UnitMarine::pre_process ---------// void UnitMarine::pre_process() { #define SURROUND_FIRM_WAIT_FACTOR 10 Unit::pre_process(); if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE) return; err_when(action_mode==ACTION_DIE || cur_action==SPRITE_DIE || hit_points<=0); if(action_mode2>=ACTION_ATTACK_UNIT && action_mode2<=ACTION_ATTACK_WALL) return; // don't process trading if unit is attacking if(auto_mode) // process trading automatically, same as caravan { if(!stop_defined_num) return; //----------------- if there is only one defined stop --------------------// if(stop_defined_num==1) { if( firm_array.is_deleted(stop_array[0].firm_recno) ) { update_stop_list(); return; } Firm *firmPtr = firm_array[stop_array[0].firm_recno]; if(firmPtr->loc_x1!=stop_array[0].firm_loc_x1 || firmPtr->loc_y1!=stop_array[0].firm_loc_y1) { update_stop_list(); return; } int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); int moveStep = move_step_magn(); if(curXLocloc_x1-moveStep || curXLoc>firmPtr->loc_x2+moveStep || curYLocloc_y1-moveStep || curYLoc>firmPtr->loc_y2+moveStep) { //### begin alex 6/10 ###// /*if((move_to_x_loc>=firmPtr->loc_x1-moveStep || move_to_x_loc<=firmPtr->loc_x2+moveStep) && (move_to_y_loc>=firmPtr->loc_y1-moveStep || move_to_y_loc<=firmPtr->loc_y2+moveStep)) return; move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id); journey_status = ON_WAY_TO_FIRM;*/ if(cur_action==SPRITE_IDLE) move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id); else journey_status = ON_WAY_TO_FIRM; //#### end alex 6/10 ####// } else { if(cur_x==next_x && cur_y==next_y && cur_action==SPRITE_IDLE) { journey_status = SURROUND_FIRM; if(nation_array[nation_recno]->get_relation(firmPtr->nation_recno)->trade_treaty) { if(wait_count<=0) { //---------- unloading goods -------------// cur_firm_recno = stop_array[0].firm_recno; get_harbor_linked_firm_info(); harbor_unload_goods(); wait_count = MAX_SHIP_WAIT_TERM*SURROUND_FIRM_WAIT_FACTOR; cur_firm_recno = 0; } else wait_count--; } } } return; } //------------ if there are more than one defined stop ---------------// err_when(stop_defined_num<=1); if(journey_status==INSIDE_FIRM) ship_in_firm(); else ship_on_way(); } else if(journey_status==INSIDE_FIRM) ship_in_firm(0); // autoMode is off } //---------- End of function UnitMarine::pre_process ----------// //--------- Begin of function UnitMarine::ship_in_firm ---------// // journey_status : INSIDE_FIRM --> ON_WAY_TO_FIRM // NO_STOP_DEFINED if no valid stop // SURROUND_FIRM if only one stop // // autoMode - 1 if autoMode is on // - 0 otherwise // void UnitMarine::ship_in_firm(int autoMode) { //-----------------------------------------------------------------------------// // the harbor is deleted while the ship is in harbor //-----------------------------------------------------------------------------// if(cur_firm_recno && firm_array.is_deleted(cur_firm_recno)) { hit_points = (float) 0; // ship also die if the harbor is deleted unit_array.disappear_in_firm(sprite_recno); // ship also die if the harnor is deleted return; } //-----------------------------------------------------------------------------// // waiting (time to upload/download cargo) //-----------------------------------------------------------------------------// if(wait_count>0) { wait_count--; return; } //-----------------------------------------------------------------------------// // leave the harbor and go to another harbor if possible //-----------------------------------------------------------------------------// ShipStop *stopPtr = stop_array + dest_stop_id - 1; int xLoc = stop_x_loc; int yLoc = stop_y_loc; Location *locPtr = world.get_loc(xLoc, yLoc); Firm *firmPtr; if(xLoc%2==0 && yLoc%2==0 && locPtr->can_move(mobile_type)) init_sprite(xLoc, yLoc); // appear in the location the unit disappeared before else { //---- the entering location is blocked, select another location to leave ----// err_when(cur_firm_recno==0); firmPtr = firm_array[cur_firm_recno]; if(appear_in_firm_surround(xLoc, yLoc, firmPtr)) { init_sprite(xLoc, yLoc); stop(); } else { wait_count = MAX_SHIP_WAIT_TERM*10; //********* BUGHERE, continue to wait or .... return; } } //-------------- get next stop id. ----------------// int nextStopId = get_next_stop_id(dest_stop_id); if(!nextStopId || dest_stop_id==nextStopId) { dest_stop_id = nextStopId; journey_status = (!nextStopId) ? NO_STOP_DEFINED : SURROUND_FIRM; return; // no stop or only one stop is valid } dest_stop_id = nextStopId; firmPtr = firm_array[stop_array[dest_stop_id-1].firm_recno]; cur_firm_recno = 0; journey_status = ON_WAY_TO_FIRM; if(autoMode) // move to next firm only if autoMode is on move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, FIRM_HARBOR); } //---------- End of function UnitMarine::ship_in_firm ----------// //--------- Begin of function UnitMarine::ship_on_way ---------// void UnitMarine::ship_on_way() { //### begin alex 6/10 ###// //FirmInfo *firmInfo = firm_res[FIRM_HARBOR]; //#### end alex 6/10 ####// if(cur_action==SPRITE_IDLE && journey_status!=SURROUND_FIRM) { if(!firm_array.is_deleted(stop_array[dest_stop_id-1].firm_recno)) { Firm *firmPtr = firm_array[stop_array[dest_stop_id-1].firm_recno]; move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, FIRM_HARBOR); int nextXLoc = next_x_loc(); int nextYLoc = next_y_loc(); int moveStep = move_step_magn(); if(nextXLoc>=firmPtr->loc_x1-moveStep && nextXLoc<=firmPtr->loc_x2+moveStep && nextYLoc>=firmPtr->loc_y1-moveStep && nextYLoc<=firmPtr->loc_y2+moveStep) journey_status = SURROUND_FIRM; return; } } err_when(cur_action==SPRITE_ATTACK || action_mode==ACTION_ATTACK_UNIT || action_mode==ACTION_ATTACK_FIRM || action_mode==ACTION_ATTACK_TOWN || action_mode==ACTION_ATTACK_WALL); if(unit_array.is_deleted(sprite_recno)) return; //-***************** BUGHERE ***************// if(firm_array.is_deleted(stop_array[dest_stop_id-1].firm_recno)) { update_stop_list(); if(stop_defined_num) // move to next stop { Firm *firmPtr = firm_array[stop_array[dest_stop_id-1].firm_recno]; move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id); } return; } ShipStop *stopPtr = stop_array + dest_stop_id - 1; Firm *firmPtr = firm_array[stopPtr->firm_recno]; int nextXLoc = next_x_loc(); int nextYLoc = next_y_loc(); int moveStep = move_step_magn(); if(journey_status==SURROUND_FIRM || ( nextXLoc==move_to_x_loc && nextYLoc==move_to_y_loc && cur_x==next_x && cur_y==next_y && // move in a tile exactly (nextXLoc>=firmPtr->loc_x1-moveStep && nextXLoc<=firmPtr->loc_x2+moveStep && nextYLoc>=firmPtr->loc_y1-moveStep && nextYLoc<=firmPtr->loc_y2+moveStep) )) { extra_move_in_beach = NO_EXTRA_MOVE; // since the ship may enter the firm in odd location stopPtr->update_pick_up(); //-------------------------------------------------------// // load/unload goods //-------------------------------------------------------// cur_firm_recno = stopPtr->firm_recno; if(nation_array[nation_recno]->get_relation(firmPtr->nation_recno)->trade_treaty) { get_harbor_linked_firm_info(); harbor_unload_goods(); if(stopPtr->pick_up_type == AUTO_PICK_UP) harbor_auto_load_goods(); else if(stopPtr->pick_up_type!=NO_PICK_UP) harbor_load_goods(); } //-------------------------------------------------------// //-------------------------------------------------------// stop_x_loc = move_to_x_loc; // store entering location stop_y_loc = move_to_y_loc; wait_count = MAX_SHIP_WAIT_TERM; // set waiting term reset_path(); deinit_sprite(1); // the ship enters the harbor now. 1-keep it selected if it is currently selected err_when(cur_x!=-1); cur_x--; // set cur_x to -2, such that invisible but still process pre_process() journey_status = INSIDE_FIRM; } else { if(cur_action!=SPRITE_MOVE) { //----------------------------------------------------// // blocked by something, go to the destination again // note: if return value is 0, cannot reach the firm. //*********BUGHERE //----------------------------------------------------// move_to_firm_surround(firmPtr->loc_x1, firmPtr->loc_y1, sprite_info->loc_width, sprite_info->loc_height, FIRM_HARBOR); journey_status = ON_WAY_TO_FIRM; } } } //---------- End of function UnitMarine::ship_on_way ----------// //--------- Begin of function UnitMarine::appear_in_firm_surround ---------// int UnitMarine::appear_in_firm_surround(int& xLoc, int& yLoc, Firm* firmPtr) { FirmInfo *firmInfo = firm_res[FIRM_HARBOR]; int firmWidth = firmInfo->loc_width; int firmHeight = firmInfo->loc_height; int smallestCount = firmWidth * firmHeight + 1; int largestCount = (firmWidth+2) * (firmHeight+2); int countLimit = largestCount - smallestCount; int count = m.random(countLimit)+smallestCount; int checkXLoc, checkYLoc, xOffset, yOffset, found=0; Location *locPtr; //-----------------------------------------------------------------// for(int i=0; iloc_x1 + xOffset; checkYLoc = firmPtr->loc_y1 + yOffset; if(checkXLoc%2 || checkYLoc%2|| checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) { count++; continue; } locPtr = world.get_loc(checkXLoc, checkYLoc); if(locPtr->can_move(mobile_type)) { found++; break; } count++; if(count > largestCount) count = smallestCount; } //-----------------------------------------------------------------// if(found) { xLoc = checkXLoc; yLoc = checkYLoc; return 1; } return 0; } //---------- End of function UnitMarine::appear_in_firm_surround ----------// //--------- Begin of function UnitMarine::get_harbor_linked_firm_info ---------// void UnitMarine::get_harbor_linked_firm_info() { FirmHarbor *firmHarborPtr = (FirmHarbor*) firm_array[cur_firm_recno]; err_when(firmHarborPtr->firm_id!=FIRM_HARBOR); firmHarborPtr->update_linked_firm_info(); linked_mine_num = firmHarborPtr->get_linked_mine_num(); linked_factory_num = firmHarborPtr->get_linked_factory_num(); linked_market_num = firmHarborPtr->get_linked_market_num(); memcpy(linked_mine_array, firmHarborPtr->linked_mine_array, sizeof(short)*MAX_LINKED_FIRM_FIRM); memcpy(linked_factory_array, firmHarborPtr->linked_factory_array, sizeof(short)*MAX_LINKED_FIRM_FIRM); memcpy(linked_market_array, firmHarborPtr->linked_market_array, sizeof(short)*MAX_LINKED_FIRM_FIRM); } //---------- End of function UnitMarine::get_harbor_linked_firm_info ----------// //--------- Begin of function UnitMarine::harbor_unload_goods ---------// void UnitMarine::harbor_unload_goods() { if(!linked_mine_num && !linked_factory_num && !linked_market_num) return; // no linked firm requires or supplys raw and product for(int i=0; i market // void UnitMarine::harbor_unload_product() { if(!linked_market_num) return; err_when(linked_market_num>MAX_LINKED_FIRM_FIRM); int i, j, k; short totalDemand; short *marketNodePtr; // point to linked_market_array char *firmSelectedPtr; // mark which firm is used FirmMarket *marketPtr; MarketGoods *marketProductPtr; MarketGoods *marketGoodsPtr; // used to find empty slot short curStock, unloadQty, useEmptySlot; for(i=0; ifirm_id != FIRM_MARKET); if(marketPtr->nation_recno!=nation_recno) continue; // don't unload goods to market of other nation if(marketPtr->ai_status==MARKET_FOR_SELL) continue; // clearing the market stock, so no unloading //---------- check the demand of this goods in the market ---------// marketProductPtr = marketPtr->market_product_array[i]; if(marketProductPtr) { err_when(marketProductPtr->product_raw_id && marketProductPtr->raw_id); totalDemand += (short)(marketPtr->max_stock_qty - marketProductPtr->stock_qty); ++*firmSelectedPtr; } else // don't have this product, clear for empty slot { marketGoodsPtr = marketPtr->market_goods_array; for(k=0; kproduct_raw_id && marketGoodsPtr->raw_id); if(!marketGoodsPtr->stock_qty && !marketGoodsPtr->supply_30days()) { empty_slot_position_array[j] = k; totalDemand += (short)marketPtr->max_stock_qty; ++*firmSelectedPtr; break; } } } } //----------------------------------------------------------------------// // distribute the stock into each market //----------------------------------------------------------------------// curStock = product_raw_qty_array[i]; marketNodePtr = linked_market_array; firmSelectedPtr = firm_selected_array; for(j=0; jfirm_id != FIRM_MARKET); marketProductPtr = marketPtr->market_product_array[i]; if(!marketProductPtr) // using empty slot, don't set the pointer to the market_goods_array until unloadQty>0 { useEmptySlot = 1; marketProductPtr = marketPtr->market_goods_array + empty_slot_position_array[j]; } else useEmptySlot = 0; unloadQty = totalDemand ? (short)((marketPtr->max_stock_qty-marketProductPtr->stock_qty)*curStock/totalDemand + 0.5) : 0; unloadQty = min((short)(marketPtr->max_stock_qty-marketProductPtr->stock_qty), unloadQty); unloadQty = min(product_raw_qty_array[i], unloadQty); if(unloadQty) { if(useEmptySlot) marketPtr->set_goods(0, i+1, empty_slot_position_array[j]); marketProductPtr->stock_qty += unloadQty; err_when(marketProductPtr->stock_qty > marketPtr->max_stock_qty); product_raw_qty_array[i] -= unloadQty; err_when(product_raw_qty_array[i] < 0); mprocessed_product_raw_qty_array[linked_mine_num+linked_factory_num+j][i] += 2; } } } } //----------- End of function UnitMarine::harbor_unload_product -----------// //--------- Begin of function UnitMarine::harbor_unload_raw ---------// // Raw material --> market and factory // void UnitMarine::harbor_unload_raw() { if(!linked_factory_num && !linked_market_num) return; err_when(linked_factory_num+linked_market_num > MAX_LINKED_FIRM_FIRM); int i, j, k; short totalDemand; short *factoryNodePtr; // point to linked_factory_array short *marketNodePtr; // point to linked_market_array char *firmSelectedPtr; // mark which firm is used (for factory and market) FirmFactory *factoryPtr; FirmMarket *marketPtr; MarketGoods *marketRawPtr; MarketGoods *marketGoodsPtr; // used to find empty slot short curStock, unloadQty, useEmptySlot; for(i=0; ifirm_id != FIRM_FACTORY); if(factoryPtr->nation_recno!=nation_recno) continue; // don't unload goods to factory of other nation if(factoryPtr->ai_status==FACTORY_RELOCATE) continue; // clearing the factory stock, so no unloading if(factoryPtr->product_raw_id-1 == i) { totalDemand = (short) (factoryPtr->max_raw_stock_qty - factoryPtr->raw_stock_qty); ++*firmSelectedPtr; } } //----------------------------------------------------------------------// // calculate the demand of this goods in market //----------------------------------------------------------------------// marketNodePtr = linked_market_array; for(j=0; jfirm_id != FIRM_MARKET); if(marketPtr->nation_recno!=nation_recno) continue; // don't unload goods to market of other nation if(marketPtr->ai_status==MARKET_FOR_SELL) continue; // clearing the market stock, so no unloading //---------- check the demand of this goods in the market ---------// marketRawPtr = marketPtr->market_raw_array[i]; if(marketRawPtr) { err_when(marketRawPtr->product_raw_id && marketRawPtr->raw_id); totalDemand += (short)(marketPtr->max_stock_qty - marketRawPtr->stock_qty); ++*firmSelectedPtr; } else // don't have this raw, clear for empty slot { marketGoodsPtr = marketPtr->market_goods_array; for(k=0; kproduct_raw_id && marketGoodsPtr->raw_id); if(!marketGoodsPtr->stock_qty && !marketGoodsPtr->supply_30days()) { empty_slot_position_array[j] = k; totalDemand += (short)marketPtr->max_stock_qty; ++*firmSelectedPtr; break; } } } } //----------------------------------------------------------------------// // distribute the stock into each factory //----------------------------------------------------------------------// curStock = raw_qty_array[i]; factoryNodePtr = linked_factory_array; firmSelectedPtr = firm_selected_array; for(j=0; jfirm_id != FIRM_FACTORY); err_when(factoryPtr->product_raw_id-1!=i); unloadQty = totalDemand ? (short)((factoryPtr->max_raw_stock_qty-factoryPtr->raw_stock_qty)*curStock/totalDemand + 0.5) : 0; unloadQty = min((short)(factoryPtr->max_raw_stock_qty-factoryPtr->raw_stock_qty), unloadQty); unloadQty = min(raw_qty_array[i], unloadQty); factoryPtr->raw_stock_qty += unloadQty; err_when(factoryPtr->raw_stock_qty > factoryPtr->max_raw_stock_qty); raw_qty_array[i] -= unloadQty; err_when(raw_qty_array[i] < 0); mprocessed_raw_qty_array[linked_mine_num+j][i] += 2; } //----------------------------------------------------------------------// // distribute the stock into each market //----------------------------------------------------------------------// marketNodePtr = linked_market_array; for(j=0; jfirm_id != FIRM_MARKET); marketRawPtr = marketPtr->market_raw_array[i]; if(!marketRawPtr) // using empty slot, don't set the pointer to the market_goods_array until unloadQty>0 { useEmptySlot = 1; marketRawPtr = marketPtr->market_goods_array + empty_slot_position_array[j]; } else useEmptySlot = 0; unloadQty = totalDemand ? (short)((marketPtr->max_stock_qty-marketRawPtr->stock_qty)*curStock/totalDemand + 0.5) : 0; unloadQty = min((short)(marketPtr->max_stock_qty-marketRawPtr->stock_qty), unloadQty); unloadQty = min(raw_qty_array[i], unloadQty); if(unloadQty) { if(useEmptySlot) marketPtr->set_goods(1, i+1, empty_slot_position_array[j]); marketRawPtr->stock_qty += unloadQty; err_when(marketRawPtr->stock_qty > marketPtr->max_stock_qty); raw_qty_array[i] -= unloadQty; err_when(raw_qty_array[i] < 0); mprocessed_raw_qty_array[linked_mine_num+linked_factory_num+j][i] += 2; } } } } //----------- End of function UnitMarine::harbor_unload_raw -----------// //--------- Begin of function UnitMarine::harbor_load_goods ---------// void UnitMarine::harbor_load_goods() { if(!linked_mine_num && !linked_factory_num && !linked_market_num) return; err_when(linked_mine_num+linked_factory_num+linked_market_num>MAX_LINKED_FIRM_FIRM); ShipStop *stopPtr = stop_array+dest_stop_id-1; if(stopPtr->pick_up_type == NO_PICK_UP) return; // return if not allowed to load any goods int pickUpType, goodsId; for(int i=0; ipick_up_array[i]) continue; pickUpType = i+1; if(pickUpType>=PICK_UP_RAW_FIRST && pickUpType<=PICK_UP_RAW_LAST) { goodsId = pickUpType-PICK_UP_RAW_FIRST; if(raw_qty_array[goodsId]=PICK_UP_PRODUCT_FIRST && pickUpType<=PICK_UP_PRODUCT_LAST) { goodsId = pickUpType-PICK_UP_PRODUCT_FIRST; if(product_raw_qty_array[goodsId]MAX_LINKED_FIRM_FIRM); int i; for(i=0; i considerMode - 1 only consider our market // - 0 only consider markets of other nation // void UnitMarine::harbor_load_product(int goodsId, int autoPickUp, int considerMode) { if(!linked_factory_num && !linked_market_num) return; if(product_raw_qty_array[goodsId]==carry_goods_capacity) return; int i; short totalSupply; short *factoryNodePtr; // point to linked_factory_array short *marketNodePtr; // point to linked_market_array char *firmSelectedPtr; // mark which firm is used (for factory and market) FirmFactory *factoryPtr; FirmMarket *marketPtr; MarketGoods *marketProductPtr; short loadQty, keepStockQty; totalSupply = 0; memset(firm_selected_array, 0, sizeof(char)*MAX_LINKED_FIRM_FIRM); firmSelectedPtr = firm_selected_array; //----------------------------------------------------------------------// // calculate the supply of this goods in factory //----------------------------------------------------------------------// if(linked_factory_num) { factoryPtr = (FirmFactory*) firm_array[linked_factory_array[0]]; keepStockQty = autoPickUp ? (short) (factoryPtr->max_stock_qty/5) : 0; } factoryNodePtr = linked_factory_array; for(i=0; ifirm_id != FIRM_FACTORY); if(considerMode) { if(factoryPtr->nation_recno!=nation_recno) continue; // not our market } else { if(factoryPtr->nation_recno==nation_recno) continue; // not consider our market for this mode } //---------- check the supply of this goods in the factory ---------// if(factoryPtr->product_raw_id!=goodsId+1) continue; // incorrect product totalSupply += max((short)(factoryPtr->stock_qty-keepStockQty), 0); ++*firmSelectedPtr; } //----------------------------------------------------------------------// // calculate the supply of this goods in market //----------------------------------------------------------------------// if(linked_market_num) { marketPtr = (FirmMarket*) firm_array[linked_market_array[0]]; keepStockQty = autoPickUp ? (short) (marketPtr->max_stock_qty/5) : 0; } marketNodePtr = linked_market_array; for(i=0; ifirm_id != FIRM_MARKET); if(considerMode) { if(marketPtr->nation_recno!=nation_recno) continue; // not our market } else { if(marketPtr->nation_recno==nation_recno) continue; // not consider our market for this mode } //---------- check the supply of this goods in the market ---------// marketProductPtr = marketPtr->market_product_array[goodsId]; if(marketProductPtr) { totalSupply += max((short)(marketProductPtr->stock_qty-keepStockQty), 0); ++*firmSelectedPtr; } } Nation *nationPtr = nation_array[nation_recno]; int curDemand = carry_goods_capacity-product_raw_qty_array[goodsId]; firmSelectedPtr = firm_selected_array; //----------------------------------------------------------------------// // get the stock from each factory //----------------------------------------------------------------------// if(linked_factory_num) { factoryPtr = (FirmFactory*) firm_array[linked_factory_array[0]]; keepStockQty = autoPickUp ? (short) (factoryPtr->max_stock_qty/5) : 0; } factoryNodePtr = linked_factory_array; for(i=0; ifirm_id != FIRM_FACTORY); err_when(factoryPtr->product_raw_id-1!=goodsId); loadQty = max((short) (factoryPtr->stock_qty-keepStockQty), 0); loadQty = totalSupply ? min((short) ((float)loadQty*curDemand/totalSupply), loadQty) : 0; if(factoryPtr->nation_recno!=nation_recno) { loadQty = (nationPtr->cash>0) ? (short) min(nationPtr->cash/PRODUCT_PRICE, loadQty) : 0; if(loadQty) nationPtr->import_goods(IMPORT_PRODUCT, factoryPtr->nation_recno, (float)loadQty*PRODUCT_PRICE); } factoryPtr->stock_qty -= loadQty; err_when(factoryPtr->stock_qty < 0); product_raw_qty_array[goodsId] += loadQty; err_when(product_raw_qty_array[goodsId] > carry_goods_capacity); } //----------------------------------------------------------------------// // get the stock from each market //----------------------------------------------------------------------// if(linked_market_num) { marketPtr = (FirmMarket*) firm_array[linked_market_array[0]]; keepStockQty = autoPickUp ? (short) (marketPtr->max_stock_qty/5) : 0; } marketNodePtr = linked_market_array; for(i=0; ifirm_id != FIRM_MARKET); marketProductPtr = marketPtr->market_product_array[goodsId]; loadQty = max((short) marketProductPtr->stock_qty-keepStockQty, 0); loadQty = totalSupply ? min((short) ((float)loadQty*curDemand/totalSupply), loadQty) : 0; if(marketPtr->nation_recno!=nation_recno) { loadQty = (nationPtr->cash>0) ? (short) min(nationPtr->cash/PRODUCT_PRICE, loadQty) : 0; if(loadQty) nationPtr->import_goods(IMPORT_PRODUCT, marketPtr->nation_recno, (float)loadQty * PRODUCT_PRICE); } marketProductPtr->stock_qty -= loadQty; err_when(marketProductPtr->stock_qty < 0); product_raw_qty_array[goodsId] += loadQty; err_when(product_raw_qty_array[goodsId] > carry_goods_capacity); } } //----------- End of function UnitMarine::harbor_load_product -----------// //--------- Begin of function UnitMarine::harbor_load_raw ---------// // considerMode - 1 only consider our market // - 0 only consider markets of other nation // void UnitMarine::harbor_load_raw(int goodsId, int autoPickUp, int considerMode) { if(!linked_mine_num && !linked_market_num) return; if(raw_qty_array[goodsId]==carry_goods_capacity) return; int i; short totalSupply; short *mineNodePtr; // point to linked_factory_array short *marketNodePtr; // point to linked_market_array char *firmSelectedPtr; // mark which firm is used (for factory and market) FirmMine *minePtr; FirmMarket *marketPtr; MarketGoods *marketRawPtr; short loadQty, keepStockQty; totalSupply = 0; memset(firm_selected_array, 0, sizeof(char)*MAX_LINKED_FIRM_FIRM); firmSelectedPtr = firm_selected_array; //----------------------------------------------------------------------// // calculate the supply of this goods in mine //----------------------------------------------------------------------// if(linked_mine_num) { minePtr = (FirmMine*) firm_array[linked_mine_array[0]]; keepStockQty = autoPickUp ? (short) (minePtr->max_stock_qty/5) : 0; } mineNodePtr = linked_mine_array; for(i=0; ifirm_id != FIRM_MINE); if(considerMode) { if(minePtr->nation_recno!=nation_recno) continue; // not our market } else { if(minePtr->nation_recno==nation_recno) continue; // not consider our market for this mode } //---------- check the supply of this goods in the mine ---------// if(minePtr->raw_id!=goodsId+1) continue; // incorrect goods totalSupply += max((short)(minePtr->stock_qty-keepStockQty), 0); ++*firmSelectedPtr; } //----------------------------------------------------------------------// // calculate the supply of this goods in market //----------------------------------------------------------------------// if(linked_market_num) { marketPtr = (FirmMarket*) firm_array[linked_market_array[0]]; keepStockQty = autoPickUp ? (short) (marketPtr->max_stock_qty/5) : 0; } marketNodePtr = linked_market_array; for(i=0; ifirm_id != FIRM_MARKET); if(considerMode) { if(marketPtr->nation_recno!=nation_recno) continue; // not our market } else { if(marketPtr->nation_recno==nation_recno) continue; // not consider our market for this mode } //---------- check the supply of this goods in the market ---------// marketRawPtr = marketPtr->market_raw_array[goodsId]; if(marketRawPtr) { totalSupply += max((short)(marketRawPtr->stock_qty-keepStockQty), 0); ++*firmSelectedPtr; } } Nation *nationPtr = nation_array[nation_recno]; int curDemand = carry_goods_capacity-raw_qty_array[goodsId]; firmSelectedPtr = firm_selected_array; //----------------------------------------------------------------------// // get the stock from each mine //----------------------------------------------------------------------// if(linked_mine_num) { minePtr = (FirmMine*) firm_array[linked_mine_array[0]]; keepStockQty = autoPickUp ? (short) (minePtr->max_stock_qty/5) : 0; } mineNodePtr = linked_mine_array; for(i=0; ifirm_id != FIRM_MINE); err_when(minePtr->raw_id-1!=goodsId); loadQty = max((short) (minePtr->stock_qty-keepStockQty), 0); loadQty = totalSupply ? min((short) ((float)loadQty*curDemand/totalSupply), loadQty) : 0; if(minePtr->nation_recno!=nation_recno) { loadQty = (nationPtr->cash>0) ? (short) min(nationPtr->cash/RAW_PRICE, loadQty) : 0; if(loadQty) nationPtr->import_goods(IMPORT_RAW, minePtr->nation_recno, (float)loadQty*RAW_PRICE); } minePtr->stock_qty -= loadQty; err_when(minePtr->stock_qty < 0); raw_qty_array[goodsId] += loadQty; err_when(raw_qty_array[goodsId] > carry_goods_capacity); } //----------------------------------------------------------------------// // get the stock from each market //----------------------------------------------------------------------// if(linked_market_num) { marketPtr = (FirmMarket*) firm_array[linked_market_array[0]]; keepStockQty = autoPickUp ? (short) (marketPtr->max_stock_qty/5) : 0; } marketNodePtr = linked_market_array; for(i=0; ifirm_id != FIRM_MARKET); marketRawPtr = marketPtr->market_raw_array[goodsId]; loadQty = max((short) marketRawPtr->stock_qty-keepStockQty, 0); loadQty = totalSupply ? min((short) ((float)loadQty*curDemand/totalSupply), loadQty) : 0; if(marketPtr->nation_recno!=nation_recno) { loadQty = (nationPtr->cash>0) ? (short) min(nationPtr->cash/RAW_PRICE, loadQty) : 0; if(loadQty) nationPtr->import_goods(IMPORT_RAW, marketPtr->nation_recno, (float)loadQty * RAW_PRICE); } marketRawPtr->stock_qty -= loadQty; err_when(marketRawPtr->stock_qty < 0); raw_qty_array[goodsId] += loadQty; err_when(raw_qty_array[goodsId] > carry_goods_capacity); } } //----------- End of function UnitMarine::harbor_load_raw -----------//