/**************************************************************************
* # # # ## # # ### ## ## ### http://www.lyonesse.it *
* # # # # # ## # # # # # *
* # # # # # ## ## # # ## ## ## # # ## *
* # # # # # ## # # # # # # # # # # # *
* ### # ## # # ### ## ## ### # # #### ## Ver. 1.0 *
* *
* -Based on CircleMud & Smaug- Copyright (c) 2001-2002 by Mithrandir *
* *
* ********************************************************************** *
* *
* File: economy.c *
* *
* Economy code *
* *
**************************************************************************/
#include "conf.h"
#include "sysdep.h"
#include <math.h>
#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "db.h"
#include "handler.h"
#include "interpreter.h"
/* external globals */
extern GOOD_DATA *goods_table[MAX_GOOD];
extern MARKET_GOOD *GoodsMarkets[MAX_GOOD][MAX_MARKET];
extern TRADING_POST *first_trading_post;
extern int top_goods;
/* externa funcs */
GOOD_DATA *get_good(int gnum);
GOOD_DATA *get_good_by_name(char *gname);
MARKET_DATA *find_market(int vnum);
MARKET_DATA *find_market_by_name(char *mname);
TRADING_POST *find_trading_post(int vnum);
TRP_GOOD *tp_has_goods(TRADING_POST *pTp, int gnum);
OBJ_DATA *create_good_obj(GOOD_DATA *pGood, int amount);
OBJ_DATA *get_good_object(OBJ_DATA *list, int gnum);
bool get_good_in_market(MARKET_DATA *pMk, int gnum);
int can_take_obj(CHAR_DATA *ch, OBJ_DATA *obj);
int Season(void);
char *get_spell_name(char *argument);
void SaveGoodsMarketsTable(bool bTime);
void LoadGoodsMarketsTable(void);
void UpdateMarketAffections(void);
void RollMarketAffections(void);
void SaveMarkets(void);
void SaveTradingPost(void);
#define COEF_DIV 2000
/* locals */
int calc_trade_value(int gnum, int mnum);
void calc_price(MARKET_DATA *pMk, GOOD_DATA *pGood, MARKET_GOOD *pGM);
/* =============================================================== */
/* calcolo del consumo e della produzione */
void consume_produce_goods(void)
{
MARKET_DATA *pMk;
GOOD_DATA *pGood;
MARKET_GOOD *pGM;
TRADING_POST *pTp;
TRP_GOOD *tGood;
double gprod, cons, rand_cons;
int qty;
// ciclo in tutti i TP in tutti i MA
for (pTp = first_trading_post; pTp; pTp = pTp->next)
{
// inizializza MA
pMk = pTp->market;
// ciclo in tutte le GTP del TP
for (tGood = pTp->first_tpgood; tGood; tGood = tGood->next)
{
// se non trova la GO, passa alla GTP successiva
if (!(pGood = get_good(tGood->goods_vnum)))
continue;
// se la GO non e' assegnata a nessun mercato, passa alla GTP successiva
if (!pGood->mkvnum)
continue;
// inizializza GM, se non c'e' passa alla GTP successiva
if (!(pGM = GoodsMarkets[pGood->vnum][pMk->vnum]))
continue;
cons = 0; rand_cons = 0; qty = 0;
// get base production
gprod = (double) pGood->gtype->prod_avg[Season()];
// calc consumption
cons = (double) (pGood->gtype->cons_speed * tGood->quantity);
// se la GO e' a stock esegue la produzione interna
if (tGood->stock)
{
int tmp1;
double var2, var3;
gprod *= pMk->var_mod.prod_var;
// calcola Random_Consumption
var3 = (double) abs(cons - gprod);
if (var3 < 0.3)
var3 = 0.3;
tmp1 = number(-1, 1);
var2 = ((double) tmp1) * ((double) cons) / var3;
rand_cons = ((double) cons) + var2;
// calcola la nuova quantita' della GTP
var3 = (double) (2 * (tGood->quantity - tGood->prev_qty) / 3);
var2 = ((double) tGood->quantity) + var3 + (((double)gprod) - rand_cons);
qty = MAX(0, (int) var2);
}
// Produzione osmotica
else
{
// inizializza MA relativo al mercato di origine
MARKET_DATA *orig_mk = find_market(pGood->mkvnum);
int iDist, tmp1;
double var1, var2, var3;
// se non esiste il MA, passa alla GTP successiva
if (!orig_mk)
continue;
// calcola la distanza tra il MA di origine ed il MA in cui sono
iDist = (int)distance(orig_mk->heart.x, orig_mk->heart.y, pMk->heart.x, pMk->heart.y);
// calcola GM.Commercial_productivity
gprod *= orig_mk->var_mod.prod_var;
var3 = (double) gprod / COEF_DIV * iDist;
var1 = (double) gprod - var3;
var2 = (double) (var1 * pGM->comm_closure * pMk->var_mod.closure_var);
pGM->comm_prod = (float) var2;
// calcola Random_Consumption
var3 = abs(cons - pGM->comm_prod);
if (var3 < 0.3)
var3 = 0.3;
tmp1 = number(-1, 1);
var2 = (double) (tmp1 * cons / var3);
rand_cons = (double) (cons + var2);
// calcola la nuova quantita' della GTP
var3 = (double) (2 * (tGood->quantity - tGood->prev_qty) / 3);
var2 = (double) (tGood->quantity + var3 + (pGM->comm_prod - rand_cons));
qty = MAX(0, (int) var2);
}
// aggiorna la quantita' del GM
pGM->qty = MAX(0, pGM->qty - tGood->quantity);
pGM->qty += qty;
// aggiorna la quantita' della GTP
tGood->prev_qty = tGood->quantity;
tGood->quantity = qty;
}
}
}
/* calcolo della domanda e dei prezzi */
void calc_demands_and_prices(FILE *fp)
{
MARKET_DATA *pMk;
GOOD_DATA *pGood;
MARKET_GOOD *pGM;
int mnum, gnum;
int avg_qty, iDist;
double tmpqty, negqty;
int buyprice;
// scorre tutti i MA
for (mnum = 0; mnum < MAX_MARKET; mnum++)
{
// ottiene MA
if (!(pMk = find_market(mnum)))
continue;
// skip unused markets
if (!pMk->size)
continue;
// scorre tutte le GO
for (gnum = 0; gnum < MAX_GOOD; gnum++)
{
// ottiene GO
if (!(pGood = get_good(gnum)))
continue;
// skip unused goods
if (!pGood->mkvnum)
continue;
// ottiene GM
if (!(pGM = GoodsMarkets[gnum][mnum]))
{
if (fp)
{
buyprice = calc_trade_value(gnum, mnum);
//fprintf(fp, "Good: %d - Market %d - (Stock: %d) - P:No - Qty: [%5d] Sell Price: [%5d] Buy Price: [%5d]\n",
// pGood->vnum, pMk->vnum, (pGood->market == mnum ? 1 : 0), 0, 0, buyprice);
fprintf(fp, "%d;%d;%d;No;000.00;000.00;%d;%d;%d\n",
pGood->vnum, pMk->vnum, (pGood->mkvnum == mnum ? 1 : 0), 0, 0, buyprice);
}
continue;
}
avg_qty = 0; iDist = 0;
// GO interno
if (pGood->mkvnum == mnum)
{
// calcola Market_Good_Medium_quantity_internal
avg_qty = pGood->gtype->prod_avg[Season()] * pMk->var_mod.prod_var / pGood->gtype->cons_speed * pGM->total_tp;
}
// GO osmotico
else
{
// ottiene MA di origine (solo per il calcolo della distanza)
MARKET_DATA *orig_mk = find_market(pGood->mkvnum);
// calcola Market_Good_Medium_quantity_external
avg_qty = pGM->comm_prod / pGood->gtype->cons_speed * pGM->total_tp;
// calcola la distanza tra i MA
iDist = (int)distance(orig_mk->heart.x, orig_mk->heart.y, pMk->heart.x, pMk->heart.y);
}
// calcola la domanda
if ( avg_qty == 0 )
pGM->demand = 10;
else
{
tmpqty = - pGM->qty;
tmpqty /= avg_qty;
negqty = exp(tmpqty);
pGM->demand = (float) (10 * negqty);
}
// calcola il prezzo di vendita
pGM->price = pGood->cost * pMk->var_mod.price_var + pGood->gtype->elasticity * (pGM->demand / 10) * pGood->cost + pGood->cost * pGM->good_appet * iDist / (COEF_DIV * 5 / 4) * pGood->gtype->elasticity;
if (fp)
{
// Prezzo PG
buyprice = pGM->price - pGood->cost * pGood->gtype->elasticity * (pGM->demand / 10);
if (buyprice < 0)
buyprice = pGood->cost / 2;
//fprintf(fp, "Good: %d - Market %d - (Stock: %d) - P:Yes - Qty: [%5d] Sell Price: [%5d] Buy Price: [%5d]\n",
// pGood->vnum, pMk->vnum, (pGood->market == mnum ? 1 : 0), pGM->qty, pGM->price, buyprice);
fprintf(fp, "%d;%d;%d;Yes;%d;%d;%d\n",
pGood->vnum, pMk->vnum, (pGood->mkvnum == mnum ? 1 : 0), pGM->qty, pGM->price, buyprice);
}
}
}
}
/* called from another_hour() in weather.c */
void SimulateEconomy(void)
{
consume_produce_goods();
calc_demands_and_prices(NULL);
SaveGoodsMarketsTable(0);
SaveMarkets();
SaveTradingPost();
}
/* Immortal command to force X resets */
ACMD(do_economy)
{
char arg[MAX_INPUT_LENGTH];
int cn, count = 0;
one_argument(argument, arg);
if (!*arg || !is_number(arg))
count = 1;
else
count = atoi(arg);
count++;
for (cn = 1; cn < count; cn++)
{
if (!(cn % 4))
UpdateMarketAffections();
consume_produce_goods();
calc_demands_and_prices(NULL);
if (!(cn % 102))
RollMarketAffections();
}
SaveGoodsMarketsTable(0);
SaveMarkets();
SaveTradingPost();
}
/* ============================================================= */
/* =========================================================================== */
/* Trading code */
/* =========================================================================== */
void list_goods_in_tp(CHAR_DATA *ch)
{
TRADING_POST *tp = NULL;
TRP_GOOD *tGood;
GOOD_DATA *pGood;
MARKET_GOOD *pGM;
char gname[MAX_STRING_LENGTH];
if (!ch->in_building)
return;
if (!(tp = ch->in_building->trp))
return;
if (!tp->first_tpgood)
{
send_to_char("Nothing at stock at the moment.\r\n", ch);
return;
}
send_to_char(
"The following goods are available:\r\n"
"-----------------------------------------------------------------\r\n"
"name description qty cost\r\n"
"-----------------------------------------------------------------\r\n"
, ch);
for (tGood = tp->first_tpgood; tGood; tGood = tGood->next)
{
if (!tGood->quantity)
continue;
if (!(pGood = get_good(tGood->goods_vnum)))
continue;
if (!(pGM = GoodsMarkets[pGood->vnum][tp->market->vnum]))
continue;
sprintf(gname, "%s %s of %s", AN(pGood->unit), pGood->unit, pGood->name);
ch_printf(ch, "%s%-15s&0 %-25s %3d %4d [%4d]\r\n",
tGood->stock ? "&b&7" : "",
pGood->name,
gname, tGood->quantity,
pGM->price, pGood->cost);
}
send_to_char("-----------------------------------------------------------------\r\n", ch);
}
/* calculate trade value */
int calc_trade_value(int gnum, int mnum)
{
GOOD_DATA *pGood;
MARKET_DATA *pMk;
MARKET_GOOD *pGM;
int price, value = 0;
float dem;
// non-existant good exits here
if (!(pGood = get_good(gnum))) return (0);
// unused good exits here
if (!pGood->mkvnum) return (0);
// non-existant market exits here
if (!(pMk = find_market(mnum))) return (0);
/*
* missing data for this good in this market..
* "simulate" good price in market calc'd with demand = 10;
*/
if (!(pGM = GoodsMarkets[pGood->vnum][pMk->vnum]))
{
MARKET_DATA *orig_mk = find_market(pGood->mkvnum);
int iDist = (int)distance(orig_mk->heart.x, orig_mk->heart.y, pMk->heart.x, pMk->heart.y);
price = pGood->cost * pMk->var_mod.price_var + pGood->gtype->elasticity * 1 * pGood->cost + pGood->cost * 1 * iDist / (COEF_DIV * 5 / 4) * pGood->gtype->elasticity;
dem = 10;
}
else
{
price = pGM->price;
dem = pGM->demand;
}
value = price - pGood->cost * pGood->gtype->elasticity * (dem / 10);
// per evitare i prezzi negativi
if (value < 0)
value = pGood->cost / 2;
return (value);
}
/*
* buy goods from TP
*
* buy 'goods name'
* buy 'goods name' <amount>
*/
void char_buy_goods(CHAR_DATA *ch, char *argument)
{
GOOD_DATA *pGood = NULL;
OBJ_DATA *obj = NULL;
TRADING_POST *pTp = NULL;
TRP_GOOD *tGood = NULL;
MARKET_GOOD *pGM = NULL;
char arg1[MAX_INPUT_LENGTH], sbaf[256], *g;
int amount, price = 0;
/* get: blank, spell name, target name */
g = get_spell_name(argument);
if (g == NULL)
{
send_to_char("Usage: buy 'good name' <amount>\r\n", ch);
return;
}
argument = strtok(NULL, "\0");
if (!(pGood = get_good_by_name(g)))
{
ch_printf(ch, "There is no good called '%s'.\r\n", g);
return;
}
if (ch->in_building && ch->in_building->trp)
pTp = ch->in_building->trp;
if (!pTp)
{
send_to_char("You must be in a trading post in order to buy goods.\r\n", ch);
return;
}
if (!(tGood = tp_has_goods(pTp, pGood->vnum)))
{
ch_printf(ch, "Here you cannot buy any good called '%s'.\r\n", g);
return;
}
one_argument(argument, arg1);
if (!*arg1 || !is_number(arg1))
amount = 1;
else
amount = atoi(arg1);
if (amount > tGood->quantity)
{
ch_printf(ch, "We don't have so many '%s'.\r\n", pGood->name);
return;
}
if (!(pGM = GoodsMarkets[pGood->vnum][pTp->market->vnum]))
{
send_to_char("Sorry but you cannot buy that now.\r\n", ch);
return;
}
price = pGM->price * amount;
if (get_gold(ch) < price && !IS_GOD(ch))
{
send_to_char("You don't have enough money.\r\n", ch);
return;
}
obj = create_good_obj(pGood, amount);
GET_OBJ_COST(obj) = pGM->price;
if (!can_take_obj(ch, obj))
{
extract_obj(obj);
return;
}
if (!IS_GOD(ch))
sub_gold(ch, price);
/* message to char */
if (obj->count > 1)
sprintf(sbaf, "You pay %d for %d $p.", price, obj->count);
else
sprintf(sbaf, "You pay %d for $p.", price);
act(sbaf, FALSE, ch, obj, NULL, TO_CHAR);
/* message to room */
if (obj->count > 1)
strcpy(sbaf, "$n buys some $o.");
else
strcpy(sbaf, "$n buys $p.");
act(sbaf, TRUE, ch, obj, NULL, TO_ROOM);
GET_OBJ_VAL(obj, 1) = pTp->vnum;
obj = obj_to_char(obj, ch);
// decrease trading post's goods quantity
tGood->quantity -= amount;
// decrease market quantity
pGM->qty -= amount;
SaveTradingPost();
}
/*
* value goods in TP
*
* value 'goods name'
* value 'goods name' <amount>
*/
void char_value_goods(CHAR_DATA *ch, char *argument)
{
GOOD_DATA *goods = NULL;
OBJ_DATA *obj = NULL;
TRADING_POST *pTp = NULL;
char arg1[MAX_INPUT_LENGTH], *g;
int price, amount;
/* get: blank, spell name, target name */
g = get_spell_name(argument);
if (g == NULL)
{
send_to_char("Usage: value 'goods name'\r\n", ch);
return;
}
argument = strtok(NULL, "\0");
if (!(goods = get_good_by_name(g)))
{
ch_printf(ch, "There is no goods called '%s'.\r\n", g);
return;
}
if (ch->in_building && ch->in_building->trp)
pTp = ch->in_building->trp;
if (!pTp)
{
send_to_char("You must be in a trading post in order to value goods.\r\n", ch);
return;
}
if (!pTp->market)
{
log("SYSERR: char_value_goods() - invalid market pointer in TP %d.\r\n", pTp->vnum);
send_to_char("This trading post has some problems. Contact an Immortal please.\r\n", ch);
return;
}
/* look if char has the goods object in his inventory */
if (!(obj = get_good_object(ch->last_carrying, goods->vnum)))
{
send_to_char("You don't have it.\r\n", ch);
return;
}
one_argument(argument, arg1);
if (!*arg1 || !is_number(arg1))
amount = obj->count;
else
amount = atoi(arg1);
if (!(price = calc_trade_value(GET_OBJ_VAL(obj, 0), pTp->market->vnum)))
{
log("SYSERR: cannot calculate trade value for good %d.", GET_OBJ_VAL(obj, 0));
send_to_char("Got a problem, contact an immortal.\r\n", ch);
return;
}
if (amount > 1)
ch_printf(ch, "You will receive %d gold coins for %d %s.", price * amount, amount, obj->short_description);
else
ch_printf(ch, "You will receive %d gold coins for %s.", price, obj->short_description);
}
/*
* sell goods in TP
*
* sell 'goods name' <amount>
*/
void char_sell_goods(CHAR_DATA *ch, char *argument)
{
GOOD_DATA *pGood = NULL;
OBJ_DATA *obj = NULL;
TRADING_POST *pTp = NULL;
TRP_GOOD *tGood = NULL;
MARKET_GOOD *pGM = NULL;
char arg1[MAX_INPUT_LENGTH], lbuf[MAX_STRING_LENGTH], *g;
int price, amount;
/* get: blank, spell name, target name */
g = get_spell_name(argument);
if (g == NULL)
{
send_to_char("Usage: sell 'good name' <amount>\r\n", ch);
return;
}
argument = strtok(NULL, "\0");
if (!(pGood = get_good_by_name(g)))
{
ch_printf(ch, "There is no goods called '%s'.\r\n", g);
return;
}
if (ch->in_building && ch->in_building->trp)
pTp = ch->in_building->trp;
if (!pTp)
{
send_to_char("You must be in a trading post in order to sell goods.\r\n", ch);
return;
}
if (!pTp->market)
{
log("SYSERR: char_sell_goods() - invalid market pointer in TP %d.\r\n", pTp->vnum);
send_to_char("This trading post has some problems. Contact an Immortal please.\r\n", ch);
return;
}
/* look if char has the goods object in his inventory */
if (!(obj = get_good_object(ch->last_carrying, pGood->vnum)))
{
send_to_char("You don't have it.\r\n", ch);
return;
}
one_argument(argument, arg1);
if (!*arg1 || !is_number(arg1))
amount = obj->count; // default to all
else
amount = atoi(arg1);
if (obj->count > amount)
{
ch_printf(ch, "You don't have so many %s.\r\n", pGood->name);
return;
}
if (!(price = calc_trade_value(GET_OBJ_VAL(obj, 0), pTp->market->vnum)))
{
log("SYSERR: cannot calculate trade value for good %d.", GET_OBJ_VAL(obj, 0));
send_to_char("Got a problem, contact an immortal.\r\n", ch);
return;
}
// add good to tp
if (!(tGood = tp_has_goods(pTp, pGood->vnum)))
{
CREATE(tGood, TRP_GOOD, 1);
tGood->next = NULL;
tGood->prev = NULL;
tGood->goods_vnum = pGood->vnum;
tGood->quantity = 0;
tGood->prev_qty = 0;
tGood->stock = 0;
LINK(tGood, pTp->first_tpgood, pTp->last_tpgood, next, prev);
}
tGood->quantity += amount;
// good previously unused.. initialize.
if (!pGood->mkvnum)
pGood->mkvnum = pTp->market->vnum;
// if not present, create GM data
if (!(pGM = GoodsMarkets[pGood->vnum][pTp->market->vnum]))
{
CREATE(pGM, MARKET_GOOD, 1);
pGM->comm_closure = 1.00;
pGM->comm_prod = 1.00;
pGM->demand = 0;
pGM->good_appet = 1;
pGM->price = pGood->cost;
pGM->qty = 0;
pGM->total_tp = 0;
GoodsMarkets[pGood->vnum][pTp->market->vnum] = pGM;
}
pGM->total_tp++;
pGM->qty += tGood->quantity;
calc_price(pTp->market, pGood, pGM);
// message to char
sprintf(lbuf, "You sell %d $o and receive %d gold coins.", amount, price * amount);
act(lbuf, FALSE, ch, obj, NULL, TO_CHAR);
// message to room
sprintf(lbuf, "$n sells %d $o and receives %d gold coins.", amount, price * amount);
act(lbuf, FALSE, ch, obj, NULL, TO_ROOM);
create_amount(price * amount, ch, NULL, NULL, NULL, FALSE);
extract_obj(obj);
SaveGoodsMarketsTable(0);
SaveTradingPost();
}
/* *************************************************************** */
SPECIAL(tradingpost)
{
if (CMD_IS("list"))
{
list_goods_in_tp(ch);
return (1);
}
if (CMD_IS("buy"))
{
if (!*argument)
send_to_char("Usage: buy 'goods name' <amount>\r\n", ch);
else
char_buy_goods(ch, argument);
return (1);
}
if (CMD_IS("sell"))
{
if (!*argument)
send_to_char("Usage: sell 'goods name' <amount>\r\n", ch);
else
char_sell_goods(ch, argument);
return (1);
}
if (CMD_IS("value"))
{
if (!*argument)
send_to_char("Usage: value 'goods name'\r\n", ch);
else
char_value_goods(ch, argument);
return (1);
}
return (0);
}
/* ------------------------------------------------------ */
/*
* I know, I know, these two functions are duplicates of the
* inner loops of consume_produce_goods() and calc_demands_and_prices()
* functions above in the code.
*
* These below are used by ACMD(do_tp) in goods.c, and are unused in the
* mentioned functions because the first time I modified the code
* everything started to go bad (really really bad!).
*
* So, inner loops have been restored, and these two continue to be
* used by ACMD(do_tp) and everyone is happy... silly reason, but... :-))
*
*/
void calc_prod(MARKET_DATA *pMk, GOOD_DATA *pGood, TRP_GOOD *tGood, MARKET_GOOD *pGM)
{
int cons = 0, qty = 0, gprod;
int tmp1 = 0;
double rand_cons = 0;
double var1 = 0, var2 = 0, var3 = 0;
// get base production
gprod = pGood->gtype->prod_avg[Season()];
// calc consumption
cons = pGood->gtype->cons_speed * tGood->quantity;
// se la GO e' a stock esegue la produzione interna
if (tGood->stock)
{
gprod *= pMk->var_mod.prod_var;
// calcola Random_Consumption
var3 = (double) abs(cons - gprod);
if (var3 < 0.3)
var3 = 0.3;
tmp1 = number(-1, 1);
var2 = (double) (tmp1 * cons / var3);
rand_cons = (double) (cons + var2);
// calcola la nuova quantita' della GTP
var3 = (double) (2 * (tGood->quantity - tGood->prev_qty) / 3);
var2 = (double) (tGood->quantity + var3 + (gprod - rand_cons));
//var1 = (double) (pMk->var_mod.prod_var * var2);
qty = MAX(0, (int) var2);
}
// Produzione osmotica
else
{
// inizializza MA relativo al mercato di origine
MARKET_DATA *orig_mk = find_market(pGood->mkvnum);
int iDist;
// se non esiste il MA, passa alla GTP successiva
if (!orig_mk)
return;
// calcola la distanza tra il MA di origine ed il MA in cui sono
iDist = (int) distance(orig_mk->heart.x, orig_mk->heart.y, pMk->heart.x, pMk->heart.y);
// calcola GM.Commercial_productivity
gprod *= orig_mk->var_mod.prod_var;
var3 = (double) gprod / COEF_DIV * iDist;
var1 = (double) gprod - var3;
var2 = (double) (var1 * pGM->comm_closure * pMk->var_mod.closure_var);
pGM->comm_prod = (float) var2;
// calcola Random_Consumption
var3 = abs(cons - pGM->comm_prod);
if (var3 < 0.3)
var3 = 0.3;
tmp1 = number(-1, 1);
var2 = (double) (tmp1 * cons / var3);
rand_cons = (double) (cons + var2);
// calcola la nuova quantita' della GTP
var3 = (double) (2 * (tGood->quantity - tGood->prev_qty) / 3);
var2 = (double) (tGood->quantity + var3 + (pGM->comm_prod - rand_cons));
//var1 = (double) (orig_mk->var_mod.prod_var * var2);
qty = MAX(0, (int) var2);
}
// aggiorna la quantita' del GM
pGM->qty = MAX(0, pGM->qty - tGood->quantity);
pGM->qty += qty;
// aggiorna la quantita' della GTP
tGood->prev_qty = tGood->quantity;
tGood->quantity = qty;
}
void calc_price(MARKET_DATA *pMk, GOOD_DATA *pGood, MARKET_GOOD *pGM)
{
int avg_qty = 0, iDist = 0;
// GO interno
if (pGood->mkvnum == pMk->vnum)
{
// calcola Market_Good_Medium_quantity_internal
avg_qty = (pGood->gtype->prod_avg[Season()] * pMk->var_mod.prod_var) / pGood->gtype->cons_speed * pGM->total_tp;
}
// GO osmotico
else
{
// ottiene MA di origine (solo per il calcolo della distanza)
MARKET_DATA *orig_mk = find_market(pGood->mkvnum);
// calcola Market_Good_Medium_quantity_external
avg_qty = pGM->comm_prod / pGood->gtype->cons_speed * pGM->total_tp;
// calcola la distanza tra i MA
iDist = (int)distance(orig_mk->heart.x, orig_mk->heart.y, pMk->heart.x, pMk->heart.y);
}
// calcola la domanda
if ( avg_qty == 0 )
pGM->demand = 10;
else
{
double tmpqty, negqty;
tmpqty = - pGM->qty;
tmpqty /= avg_qty;
negqty = exp(tmpqty);
pGM->demand = (float) (10 * negqty);
}
// calcola il prezzo di vendita
pGM->price = pGood->cost * pMk->var_mod.price_var + pGood->gtype->elasticity * (pGM->demand / 10) * pGood->cost + pGood->cost * pGM->good_appet * iDist / (COEF_DIV * 5 / 4) * pGood->gtype->elasticity;
}