diff --git a/src/economy.c b/src/economy.c index 162ee3d61..62094e5df 100644 --- a/src/economy.c +++ b/src/economy.c @@ -88,7 +88,7 @@ static econ_request entertainers[1024]; static econ_request *nextentertainer; static int entertaining; -static econ_request *g_requests; /* TODO: no need for this to be module-global */ +static econ_request **g_requests; /* TODO: no need for this to be module-global */ #define RECRUIT_MERGE 1 static int rules_recruit = -1; @@ -141,7 +141,7 @@ static void scramble(void *data, unsigned int n, size_t width) } } -unsigned int expand_production(region * r, econ_request * requests, econ_request **results) +unsigned int expand_production(region * r, econ_request * requests, econ_request ***results) { unit *u; econ_request *o; @@ -161,24 +161,28 @@ unsigned int expand_production(region * r, econ_request * requests, econ_request if (norders > 0) { int i = 0; - econ_request *split; - split = (econ_request *)calloc(norders, sizeof(econ_request)); + econ_request **split; + split = calloc(norders, sizeof(econ_request *)); for (o = requests; o; o = o->next) { if (o->qty > 0) { unsigned int j; for (j = o->qty; j; j--) { - split[i] = *o; - split[i].unit->n = 0; + split[i] = o; + o->unit->n = 0; i++; } } } - scramble(split, norders, sizeof(econ_request)); + scramble(split, norders, sizeof(econ_request *)); *results = split; } else { *results = NULL; } + return norders; +} + +static void free_requests(econ_request *requests) { while (requests) { econ_request *req = requests->next; if (requests->ord) { @@ -187,7 +191,6 @@ unsigned int expand_production(region * r, econ_request * requests, econ_request free(requests); requests = req; } - return norders; } static unsigned int expandorders(region * r, econ_request * requests) { @@ -1479,54 +1482,54 @@ static void expandbuying(region * r, econ_request * buyorders) * G�ter pro Monat ist. j sind die Befehle, i der Index des * gehandelten Produktes. */ if (max_products > 0) { - unsigned int j; unsigned int norders = expandorders(r, buyorders); - if (!norders) - return; - for (j = 0; j != norders; j++) { - int price, multi; - ltype = g_requests[j].type.trade.ltype; - trade = trades; - while (trade->type && trade->type != ltype) - ++trade; - multi = trade->multi; - price = ltype->price * multi; + if (norders) { + unsigned int j; + for (j = 0; j != norders; j++) { + int price, multi; + ltype = g_requests[j]->type.trade.ltype; + trade = trades; + while (trade->type && trade->type != ltype) + ++trade; + multi = trade->multi; + price = ltype->price * multi; - if (get_pooled(g_requests[j].unit, rsilver, GET_DEFAULT, - price) >= price) { - item *items; - /* litems z�hlt die G�ter, die verkauft wurden, u->n das Geld, das - * verdient wurde. Dies mu� gemacht werden, weil der Preis st�ndig sinkt, - * man sich also das verdiente Geld und die verkauften Produkte separat - * merken mu�. */ - attrib *a; + if (get_pooled(g_requests[j]->unit, rsilver, GET_DEFAULT, + price) >= price) { + item *items; + /* litems z�hlt die G�ter, die verkauft wurden, u->n das Geld, das + * verdient wurde. Dies mu� gemacht werden, weil der Preis st�ndig sinkt, + * man sich also das verdiente Geld und die verkauften Produkte separat + * merken mu�. */ + attrib *a; - u = g_requests[j].unit; - a = a_find(u->attribs, &at_luxuries); - if (a == NULL) { - a = a_add(&u->attribs, a_new(&at_luxuries)); + u = g_requests[j]->unit; + a = a_find(u->attribs, &at_luxuries); + if (a == NULL) { + a = a_add(&u->attribs, a_new(&at_luxuries)); + } + items = a->data.v; + + i_change(&items, ltype->itype, 1); + a->data.v = items; + i_change(&g_requests[j]->unit->items, ltype->itype, 1); + use_pooled(u, rsilver, GET_DEFAULT, price); + if (u->n < 0) + u->n = 0; + u->n += price; + + rsetmoney(r, rmoney(r) + price); + + /* Falls mehr als max_products Bauern ein Produkt verkauft haben, steigt + * der Preis Multiplikator f�r das Produkt um den Faktor 1. Der Z�hler + * wird wieder auf 0 gesetzt. */ + if (++trade->number == max_products) { + trade->number = 0; + ++trade->multi; + } + fset(u, UFL_LONGACTION | UFL_NOTMOVING); } - items = a->data.v; - - i_change(&items, ltype->itype, 1); - a->data.v = items; - i_change(&g_requests[j].unit->items, ltype->itype, 1); - use_pooled(u, rsilver, GET_DEFAULT, price); - if (u->n < 0) - u->n = 0; - u->n += price; - - rsetmoney(r, rmoney(r) + price); - - /* Falls mehr als max_products Bauern ein Produkt verkauft haben, steigt - * der Preis Multiplikator f�r das Produkt um den Faktor 1. Der Z�hler - * wird wieder auf 0 gesetzt. */ - if (++trade->number == max_products) { - trade->number = 0; - ++trade->multi; - } - fset(u, UFL_LONGACTION | UFL_NOTMOVING); } } free(g_requests); @@ -1754,79 +1757,77 @@ static void expandselling(region * r, econ_request * sellorders, int limit) * Runde erweitert werden kann. */ norders = expandorders(r, sellorders); - if (norders == 0) { - return; - } - - for (j = 0; j != norders; j++) { - const luxury_type *search = NULL; - const luxury_type *ltype = g_requests[j].type.trade.ltype; - int multi = r_demand(r, ltype); - int i; - int use = 0; - for (i = 0, search = luxurytypes; search != ltype; search = search->next) { - /* TODO: this is slow and lame! */ - ++i; - } - if (counter[i] >= limit) - continue; - if (counter[i] + 1 > max_products && multi > 1) - --multi; - price = ltype->price * multi; - - if (money >= price) { - item *itm; - attrib *a; - u = g_requests[j].unit; - a = a_find(u->attribs, &at_luxuries); - if (!a) { - a = a_add(&u->attribs, a_new(&at_luxuries)); - } - itm = (item *)a->data.v; - i_change(&itm, ltype->itype, 1); - a->data.v = itm; - ++use; - if (u->n < 0) { - u->n = 0; + if (norders > 0) { + for (j = 0; j != norders; j++) { + const luxury_type *search = NULL; + const luxury_type *ltype = g_requests[j]->type.trade.ltype; + int multi = r_demand(r, ltype); + int i; + int use = 0; + for (i = 0, search = luxurytypes; search != ltype; search = search->next) { + /* TODO: this is slow and lame! */ + ++i; } + if (counter[i] >= limit) + continue; + if (counter[i] + 1 > max_products && multi > 1) + --multi; + price = ltype->price * multi; - if (hafenowner) { - if (hafenowner->faction != u->faction) { - int abgezogenhafen = price / 10; - hafencollected += abgezogenhafen; - price -= abgezogenhafen; - money -= abgezogenhafen; + if (money >= price) { + item *itm; + attrib *a; + u = g_requests[j]->unit; + a = a_find(u->attribs, &at_luxuries); + if (!a) { + a = a_add(&u->attribs, a_new(&at_luxuries)); + } + itm = (item *)a->data.v; + i_change(&itm, ltype->itype, 1); + a->data.v = itm; + ++use; + if (u->n < 0) { + u->n = 0; + } + + if (hafenowner) { + if (hafenowner->faction != u->faction) { + int abgezogenhafen = price / 10; + hafencollected += abgezogenhafen; + price -= abgezogenhafen; + money -= abgezogenhafen; + } + } + if (maxb) { + if (maxowner->faction != u->faction) { + int abgezogensteuer = price * tax_per_size[maxeffsize] / 100; + taxcollected += abgezogensteuer; + price -= abgezogensteuer; + money -= abgezogensteuer; + } + } + u->n += price; + change_money(u, price); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + + /* r->money -= price; --- dies wird eben nicht ausgef�hrt, denn die + * Produkte k�nnen auch als Steuern eingetrieben werden. In der Region + * wurden Silberst�cke gegen Luxusg�ter des selben Wertes eingetauscht! + * Falls mehr als max_products Kunden ein Produkt gekauft haben, sinkt + * die Nachfrage f�r das Produkt um 1. Der Z�hler wird wieder auf 0 + * gesetzt. */ + + if (++counter[i] > max_products) { + int d = r_demand(r, ltype); + if (d > 1) { + r_setdemand(r, ltype, d - 1); + } + counter[i] = 0; } } - if (maxb) { - if (maxowner->faction != u->faction) { - int abgezogensteuer = price * tax_per_size[maxeffsize] / 100; - taxcollected += abgezogensteuer; - price -= abgezogensteuer; - money -= abgezogensteuer; - } + if (use > 0) { + use_pooled(g_requests[j]->unit, ltype->itype->rtype, GET_DEFAULT, use); } - u->n += price; - change_money(u, price); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - - /* r->money -= price; --- dies wird eben nicht ausgef�hrt, denn die - * Produkte k�nnen auch als Steuern eingetrieben werden. In der Region - * wurden Silberst�cke gegen Luxusg�ter des selben Wertes eingetauscht! - * Falls mehr als max_products Kunden ein Produkt gekauft haben, sinkt - * die Nachfrage f�r das Produkt um 1. Der Z�hler wird wieder auf 0 - * gesetzt. */ - - if (++counter[i] > max_products) { - int d = r_demand(r, ltype); - if (d > 1) { - r_setdemand(r, ltype, d - 1); - } - counter[i] = 0; - } - } - if (use > 0) { - use_pooled(g_requests[j].unit, ltype->itype->rtype, GET_DEFAULT, use); } } free(g_requests); @@ -2520,8 +2521,8 @@ static void expandloot(region * r, econ_request * lootorders) int startmoney = rmoney(r); for (i = 0; i != norders && startmoney > looted + TAXFRACTION * 2; i++) { - change_money(g_requests[i].unit, TAXFRACTION); - g_requests[i].unit->n += TAXFRACTION; + change_money(g_requests[i]->unit, TAXFRACTION); + g_requests[i]->unit->n += TAXFRACTION; /*Looting destroys double the money*/ looted += TAXFRACTION * 2; } @@ -2554,8 +2555,8 @@ void expandtax(region * r, econ_request * taxorders) if (norders > 0) { unsigned int i; for (i = 0; i != norders && rmoney(r) > TAXFRACTION; i++) { - change_money(g_requests[i].unit, TAXFRACTION); - g_requests[i].unit->n += TAXFRACTION; + change_money(g_requests[i]->unit, TAXFRACTION); + g_requests[i]->unit->n += TAXFRACTION; rsetmoney(r, rmoney(r) - TAXFRACTION); } free(g_requests); @@ -2938,18 +2939,23 @@ void produce(struct region *r) if (!rule_autowork()) { expandwork(r, workers, nextworker, region_maxworkers(r)); } - if (taxorders) + if (taxorders) { expandtax(r, taxorders); + free_requests(taxorders); + } - if (lootorders) + if (lootorders) { expandloot(r, lootorders); - + free_requests(lootorders); + } /* An erster Stelle Kaufen (expandbuying), die Bauern so Geld bekommen, um * nachher zu beim Verkaufen (expandselling) den Spielern abkaufen zu * k�nnen. */ - if (buyorders) + if (buyorders) { expandbuying(r, buyorders); + free_requests(buyorders); + } if (sellorders) { int limit = rpeasants(r) / TRADE_FRACTION; @@ -2957,13 +2963,16 @@ void produce(struct region *r) && buildingtype_exists(r, caravan_bt, true)) limit *= 2; expandselling(r, sellorders, limited ? limit : INT_MAX); + free_requests(sellorders); } /* Die Spieler sollen alles Geld verdienen, bevor sie beklaut werden * (expandstealing). */ - if (stealorders) + if (stealorders) { expandstealing(r, stealorders); + free_requests(stealorders); + } assert(rmoney(r) >= 0); assert(rpeasants(r) >= 0); diff --git a/src/economy.h b/src/economy.h index 47f3e77ec..99558bf80 100644 --- a/src/economy.h +++ b/src/economy.h @@ -69,7 +69,7 @@ extern "C" { void produce(struct region *r); void auto_work(struct region *r); - unsigned int expand_production(struct region * r, struct econ_request * requests, struct econ_request **results); + unsigned int expand_production(struct region * r, struct econ_request * requests, struct econ_request ***results); typedef enum income_t { IC_WORK, IC_ENTERTAIN, IC_TAX, IC_TRADE, IC_TRADETAX, IC_STEAL, IC_MAGIC, IC_LOOT } income_t; void add_income(struct unit * u, income_t type, int want, int qty); diff --git a/src/economy.test.c b/src/economy.test.c index 1d9149ff2..d4322fef7 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -722,7 +722,7 @@ static void test_loot(CuTest *tc) { static void test_expand_production(CuTest *tc) { econ_request *orders; - econ_request *results = NULL; + econ_request **results = NULL; region *r; unit *u; @@ -735,8 +735,8 @@ static void test_expand_production(CuTest *tc) { u->n = 1; /* will be overwritten */ CuAssertIntEquals(tc, 2, expand_production(r, orders, &results)); CuAssertPtrNotNull(tc, results); - CuAssertPtrEquals(tc, u, results[0].unit); - CuAssertPtrEquals(tc, u, results[1].unit); + CuAssertPtrEquals(tc, u, results[0]->unit); + CuAssertPtrEquals(tc, u, results[1]->unit); CuAssertIntEquals(tc, 0, u->n); test_teardown(); } diff --git a/src/steal.c b/src/steal.c index f0b0d03d5..65316f1dd 100644 --- a/src/steal.c +++ b/src/steal.c @@ -51,7 +51,7 @@ void expandstealing(region * r, econ_request * stealorders) const resource_type *rsilver = get_resourcetype(R_SILVER); unsigned int j; unsigned int norders; - econ_request *requests; + econ_request **requests; assert(rsilver); @@ -68,11 +68,11 @@ void expandstealing(region * r, econ_request * stealorders) unit *u; int n = 0; - if (requests[j].unit->n > requests[j].unit->wants) { + if (requests[j]->unit->n > requests[j]->unit->wants) { break; } - u = findunitg(requests[j].type.steal.no, r); + u = findunitg(requests[j]->type.steal.no, r); if (u && u->region == r) { n = get_pooled(u, rsilver, GET_ALL, INT_MAX); @@ -82,16 +82,16 @@ void expandstealing(region * r, econ_request * stealorders) n = 10; } if (n > 0) { - int w = requests[j].unit->wants; + int w = requests[j]->unit->wants; if (n > w) n = w; use_pooled(u, rsilver, GET_ALL, n); - requests[j].unit->n = n; - change_money(requests[j].unit, n); + requests[j]->unit->n = n; + change_money(requests[j]->unit, n); ADDMSG(&u->faction->msgs, msg_message("stealeffect", "unit region amount", u, u->region, n)); } - add_income(requests[j].unit, IC_STEAL, requests[j].unit->wants, requests[j].unit->n); - fset(requests[j].unit, UFL_LONGACTION | UFL_NOTMOVING); + add_income(requests[j]->unit, IC_STEAL, requests[j]->unit->wants, requests[j]->unit->n); + fset(requests[j]->unit, UFL_LONGACTION | UFL_NOTMOVING); } free(requests); }