/*
* 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 -----------//