From 5680057e7f0c27cf90eeb81588bd5659d5be8874 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 15 Feb 2017 17:09:23 +0100 Subject: [PATCH 1/6] adding simple test for MAKE --- src/economy.c | 140 ++++++++++++++++++++++----------------------- src/economy.h | 1 + src/economy.test.c | 31 ++++++++++ src/kernel/build.c | 2 +- src/kernel/item.h | 6 +- 5 files changed, 107 insertions(+), 73 deletions(-) diff --git a/src/economy.c b/src/economy.c index dec4517a4..711a80d82 100644 --- a/src/economy.c +++ b/src/economy.c @@ -534,7 +534,7 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders) } if (has_skill(u, SK_MAGIC)) { /* error158;de;{unit} in {region}: '{command}' - Magier arbeiten - * grundsätzlich nur alleine! */ + * grunds�tzlich nur alleine! */ cmistake(u, ord, 158, MSG_EVENT); return; } @@ -895,7 +895,7 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) const resource_type *rring; int amount, skill; - /* momentan kann man keine ressourcen abbauen, wenn man dafür + /* momentan kann man keine ressourcen abbauen, wenn man daf�r * Materialverbrauch hat: */ assert(itype != NULL && (itype->construction == NULL || itype->construction->materials == NULL)); @@ -928,8 +928,8 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) } } - /* Bergwächter können Abbau von Eisen/Laen durch Bewachen verhindern. - * Als magische Wesen 'sehen' Bergwächter alles und werden durch + /* Bergw�chter k�nnen Abbau von Eisen/Laen durch Bewachen verhindern. + * Als magische Wesen 'sehen' Bergw�chter alles und werden durch * Belagerung nicht aufgehalten. (Ansonsten wie oben bei Elfen anpassen). */ if (itype->rtype && (itype->rtype == get_resourcetype(R_IRON) || itype->rtype == rt_find("laen"))) { @@ -1095,7 +1095,7 @@ leveled_allocation(const resource_type * rtype, region * r, allocation * alist) if (avail > 0) { int want = required(al->want - al->get, al->save); int x = avail * want / nreq; - /* Wenn Rest, dann würfeln, ob ich was bekomme: */ + /* Wenn Rest, dann w�rfeln, ob ich was bekomme: */ if (rng_int() % nreq < (avail * want) % nreq) ++x; avail -= x; @@ -1140,7 +1140,7 @@ attrib_allocation(const resource_type * rtype, region * r, allocation * alist) if (avail > 0) { int want = required(al->want, al->save); int x = avail * want / nreq; - /* Wenn Rest, dann würfeln, ob ich was bekomme: */ + /* Wenn Rest, dann w�rfeln, ob ich was bekomme: */ if (rng_int() % nreq < (avail * want) % nreq) ++x; avail -= x; @@ -1248,7 +1248,7 @@ static void create_potion(unit * u, const potion_type * ptype, int want) } } -static void create_item(unit * u, const item_type * itype, int want) +void make_item(unit * u, const item_type * itype, int want) { if (itype->construction && fval(itype->rtype, RTF_LIMITED)) { #if GUARD_DISABLES_PRODUCTION == 1 @@ -1402,7 +1402,7 @@ int make_cmd(unit * u, struct order *ord) } } else if (itype != NULL) { - create_item(u, itype, m); + make_item(u, itype, m); } else { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_cannotmake", "")); @@ -1453,15 +1453,15 @@ static void expandbuying(region * r, request * buyorders) return; /* Initialisation. multiplier ist der Multiplikator auf den - * Verkaufspreis. Für max_products Produkte kauft man das Produkt zum - * einfachen Verkaufspreis, danach erhöht sich der Multiplikator um 1. - * counter ist ein Zähler, der die gekauften Produkte zählt. money - * wird für die debug message gebraucht. */ + * Verkaufspreis. F�r max_products Produkte kauft man das Produkt zum + * einfachen Verkaufspreis, danach erh�ht sich der Multiplikator um 1. + * counter ist ein Z�hler, der die gekauften Produkte z�hlt. money + * wird f�r die debug message gebraucht. */ max_products = rpeasants(r) / TRADE_FRACTION; - /* Kauf - auch so programmiert, daß er leicht erweiterbar auf mehrere - * Güter pro Monat ist. j sind die Befehle, i der Index des + /* Kauf - auch so programmiert, da� er leicht erweiterbar auf mehrere + * G�ter pro Monat ist. j sind die Befehle, i der Index des * gehandelten Produktes. */ if (max_products > 0) { unsigned int j; @@ -1483,10 +1483,10 @@ static void expandbuying(region * r, request * buyorders) unit *u = g_requests[j].unit; 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, + /* 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ß. */ + * merken mu�. */ attrib *a = a_find(u->attribs, &at_luxuries); if (a == NULL) a = a_add(&u->attribs, a_new(&at_luxuries)); @@ -1503,7 +1503,7 @@ static void expandbuying(region * r, request * buyorders) 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 + * 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; @@ -1563,7 +1563,7 @@ static void buy(unit * u, request ** buyorders, struct order *ord) return; } /* Im Augenblick kann man nur 1 Produkt kaufen. expandbuying ist aber - * schon dafür ausgerüstet, mehrere Produkte zu kaufen. */ + * schon daf�r ausger�stet, mehrere Produkte zu kaufen. */ kwd = init_order(ord); assert(kwd == K_BUY); @@ -1573,7 +1573,7 @@ static void buy(unit * u, request ** buyorders, struct order *ord) return; } if (besieged(u)) { - /* Belagerte Einheiten können nichts kaufen. */ + /* Belagerte Einheiten k�nnen nichts kaufen. */ cmistake(u, ord, 60, MSG_COMMERCE); return; } @@ -1587,7 +1587,7 @@ static void buy(unit * u, request ** buyorders, struct order *ord) } } else { - /* ...oder in der Region muß es eine Burg geben. */ + /* ...oder in der Region mu� es eine Burg geben. */ building *b = 0; if (r->buildings) { static int cache; @@ -1608,11 +1608,11 @@ static void buy(unit * u, request ** buyorders, struct order *ord) } } - /* Ein Händler kann nur 10 Güter pro Talentpunkt handeln. */ + /* Ein H�ndler kann nur 10 G�ter pro Talentpunkt handeln. */ k = u->number * 10 * effskill(u, SK_TRADE, 0); - /* hat der Händler bereits gehandelt, muss die Menge der bereits - * verkauften/gekauften Güter abgezogen werden */ + /* hat der H�ndler bereits gehandelt, muss die Menge der bereits + * verkauften/gekauften G�ter abgezogen werden */ a = a_find(u->attribs, &at_trades); if (!a) { a = a_add(&u->attribs, a_new(&at_trades)); @@ -1629,7 +1629,7 @@ static void buy(unit * u, request ** buyorders, struct order *ord) } assert(n >= 0); - /* die Menge der verkauften Güter merken */ + /* die Menge der verkauften G�ter merken */ a->data.i += n; s = gettoken(token, sizeof(token)); @@ -1662,7 +1662,7 @@ static void add_income(unit * u, int type, int want, int qty) "unit region mode wanted amount", u, u->region, type, want, qty)); } -/* Steuersätze in % bei Burggröße */ +/* Steuers�tze in % bei Burggr��e */ static int tax_per_size[7] = { 0, 6, 12, 18, 24, 30, 36 }; static void expandselling(region * r, request * sellorders, int limit) @@ -1697,11 +1697,11 @@ static void expandselling(region * r, request * sellorders, int limit) } memset(counter, 0, sizeof(int) * ncounter); - if (!sellorders) { /* NEIN, denn Insekten können in || !r->buildings) */ - return; /* Sümpfen und Wüsten auch so handeln */ + if (!sellorders) { /* NEIN, denn Insekten k�nnen in || !r->buildings) */ + return; /* S�mpfen und W�sten auch so handeln */ } - /* Stelle Eigentümer der größten Burg fest. Bekommt Steuern aus jedem - * Verkauf. Wenn zwei Burgen gleicher Größe bekommt gar keiner etwas. */ + /* Stelle Eigent�mer der gr��ten Burg fest. Bekommt Steuern aus jedem + * Verkauf. Wenn zwei Burgen gleicher Gr��e bekommt gar keiner etwas. */ for (b = rbuildings(r); b; b = b->next) { if (b->size > maxsize && building_owner(b) != NULL && b->type == castle_bt) { @@ -1724,13 +1724,13 @@ static void expandselling(region * r, request * sellorders, int limit) maxowner = (unit *)NULL; } } - /* Die Region muss genug Geld haben, um die Produkte kaufen zu können. */ + /* Die Region muss genug Geld haben, um die Produkte kaufen zu k�nnen. */ money = rmoney(r); - /* max_products sind 1/100 der Bevölkerung, falls soviele Produkte + /* max_products sind 1/100 der Bev�lkerung, falls soviele Produkte * verkauft werden - counter[] - sinkt die Nachfrage um 1 Punkt. - * multiplier speichert r->demand für die debug message ab. */ + * multiplier speichert r->demand f�r die debug message ab. */ max_products = rpeasants(r) / TRADE_FRACTION; if (max_products <= 0) @@ -1798,11 +1798,11 @@ static void expandselling(region * r, request * sellorders, int limit) 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! + /* 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 + * die Nachfrage f�r das Produkt um 1. Der Z�hler wird wieder auf 0 * gesetzt. */ if (++counter[i] > max_products) { @@ -1819,7 +1819,7 @@ static void expandselling(region * r, request * sellorders, int limit) } free(g_requests); - /* Steuern. Hier werden die Steuern dem Besitzer der größten Burg gegeben. */ + /* Steuern. Hier werden die Steuern dem Besitzer der gr��ten Burg gegeben. */ if (maxowner) { if (taxcollected > 0) { change_money(maxowner, (int)taxcollected); @@ -1876,7 +1876,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord) cmistake(u, ord, 69, MSG_INCOME); return false; } - /* sellorders sind KEIN array, weil für alle items DIE SELBE resource + /* sellorders sind KEIN array, weil f�r alle items DIE SELBE resource * (das geld der region) aufgebraucht wird. */ kwd = init_order(ord); @@ -1901,13 +1901,13 @@ static bool sell(unit * u, request ** sellorders, struct order *ord) return false; } } - /* Belagerte Einheiten können nichts verkaufen. */ + /* Belagerte Einheiten k�nnen nichts verkaufen. */ if (besieged(u)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error60", "")); return false; } - /* In der Region muß es eine Burg geben. */ + /* In der Region mu� es eine Burg geben. */ if (u_race(u) == get_race(RC_INSECT)) { if (r->terrain != newterrain(T_SWAMP) && r->terrain != newterrain(T_DESERT) @@ -1917,7 +1917,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord) } } else { - /* ...oder in der Region muß es eine Burg geben. */ + /* ...oder in der Region mu� es eine Burg geben. */ building *b = 0; if (r->buildings) { for (b = r->buildings; b; b = b->next) { @@ -1930,7 +1930,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord) } } - /* Ein Händler kann nur 10 Güter pro Talentpunkt verkaufen. */ + /* Ein H�ndler kann nur 10 G�ter pro Talentpunkt verkaufen. */ n = MIN(n, u->number * 10 * effskill(u, SK_TRADE, 0)); @@ -1956,7 +1956,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord) } available = get_pooled(u, itype->rtype, GET_DEFAULT, INT_MAX); - /* Wenn andere Einheiten das selbe verkaufen, muß ihr Zeug abgezogen + /* Wenn andere Einheiten das selbe verkaufen, mu� ihr Zeug abgezogen * werden damit es nicht zweimal verkauft wird: */ for (o = *sellorders; o; o = o->next) { if (o->type.ltype == ltype && o->unit->faction == u->faction) { @@ -1973,16 +1973,16 @@ static bool sell(unit * u, request ** sellorders, struct order *ord) return false; } /* Hier wird request->type verwendet, weil die obere limit durch - * das silber gegeben wird (region->money), welches für alle + * das silber gegeben wird (region->money), welches f�r alle * (!) produkte als summe gilt, als nicht wie bei der - * produktion, wo für jedes produkt einzeln eine obere limite + * produktion, wo f�r jedes produkt einzeln eine obere limite * existiert, so dass man arrays von orders machen kann. */ - /* Ein Händler kann nur 10 Güter pro Talentpunkt handeln. */ + /* Ein H�ndler kann nur 10 G�ter pro Talentpunkt handeln. */ k = u->number * 10 * effskill(u, SK_TRADE, 0); - /* hat der Händler bereits gehandelt, muss die Menge der bereits - * verkauften/gekauften Güter abgezogen werden */ + /* hat der H�ndler bereits gehandelt, muss die Menge der bereits + * verkauften/gekauften G�ter abgezogen werden */ a = a_find(u->attribs, &at_trades); if (!a) { a = a_add(&u->attribs, a_new(&at_trades)); @@ -1993,7 +1993,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord) n = MIN(n, k); assert(n >= 0); - /* die Menge der verkauften Güter merken */ + /* die Menge der verkauften G�ter merken */ a->data.i += n; o = (request *)calloc(1, sizeof(request)); o->unit = u; @@ -2017,8 +2017,8 @@ static void expandstealing(region * r, request * stealorders) expandorders(r, stealorders); if (!norders) return; - /* Für jede unit in der Region wird Geld geklaut, wenn sie Opfer eines - * Beklauen-Orders ist. Jedes Opfer muß einzeln behandelt werden. + /* F�r jede unit in der Region wird Geld geklaut, wenn sie Opfer eines + * Beklauen-Orders ist. Jedes Opfer mu� einzeln behandelt werden. * * u ist die beklaute unit. oa.unit ist die klauende unit. */ @@ -2079,7 +2079,7 @@ static void plant(unit * u, int raw) return; } - /* Skill prüfen */ + /* Skill pr�fen */ skill = effskill(u, SK_HERBALISM, 0); if (skill < 6) { ADDMSG(&u->faction->msgs, @@ -2087,14 +2087,14 @@ static void plant(unit * u, int raw) "skill minskill product", SK_HERBALISM, 6, itype->rtype, 1)); return; } - /* Wasser des Lebens prüfen */ + /* Wasser des Lebens pr�fen */ if (get_pooled(u, rt_water, GET_DEFAULT, 1) == 0) { ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "resource_missing", "missing", rt_water)); return; } n = get_pooled(u, itype->rtype, GET_DEFAULT, skill * u->number); - /* Kräuter prüfen */ + /* Kr�uter pr�fen */ if (n == 0) { ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "resource_missing", "missing", @@ -2104,7 +2104,7 @@ static void plant(unit * u, int raw) n = MIN(skill * u->number, n); n = MIN(raw, n); - /* Für jedes Kraut Talent*10% Erfolgschance. */ + /* F�r jedes Kraut Talent*10% Erfolgschance. */ for (i = n; i > 0; i--) { if (rng_int() % 10 < skill) planted++; @@ -2129,10 +2129,10 @@ static void planttrees(unit * u, int raw) return; } - /* Mallornbäume kann man nur in Mallornregionen züchten */ + /* Mallornb�ume kann man nur in Mallornregionen z�chten */ rtype = get_resourcetype(fval(r, RF_MALLORN) ? R_MALLORNSEED : R_SEED); - /* Skill prüfen */ + /* Skill pr�fen */ skill = effskill(u, SK_HERBALISM, 0); if (skill < 6) { ADDMSG(&u->faction->msgs, @@ -2157,7 +2157,7 @@ static void planttrees(unit * u, int raw) } n = MIN(raw, n); - /* Für jeden Samen Talent*10% Erfolgschance. */ + /* F�r jeden Samen Talent*10% Erfolgschance. */ for (i = n; i > 0; i--) { if (rng_int() % 10 < skill) planted++; @@ -2172,7 +2172,7 @@ static void planttrees(unit * u, int raw) "unit region amount herb", u, r, planted, rtype)); } -/* züchte bäume */ +/* z�chte b�ume */ static void breedtrees(unit * u, int raw) { int n, i, skill, planted = 0; @@ -2184,7 +2184,7 @@ static void breedtrees(unit * u, int raw) get_gamedate(turn, &date); current_season = date.season; - /* Bäume züchten geht nur im Frühling */ + /* B�ume z�chten geht nur im Fr�hling */ if (current_season != SEASON_SPRING) { planttrees(u, raw); return; @@ -2194,10 +2194,10 @@ static void breedtrees(unit * u, int raw) return; } - /* Mallornbäume kann man nur in Mallornregionen züchten */ + /* Mallornb�ume kann man nur in Mallornregionen z�chten */ rtype = get_resourcetype(fval(r, RF_MALLORN) ? R_MALLORNSEED : R_SEED); - /* Skill prüfen */ + /* Skill pr�fen */ skill = effskill(u, SK_HERBALISM, 0); if (skill < 12) { planttrees(u, raw); @@ -2207,7 +2207,7 @@ static void breedtrees(unit * u, int raw) /* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */ raw = MIN(skill * u->number, raw); n = get_pooled(u, rtype, GET_DEFAULT, raw); - /* Samen prüfen */ + /* Samen pr�fen */ if (n == 0) { ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype)); @@ -2215,7 +2215,7 @@ static void breedtrees(unit * u, int raw) } n = MIN(raw, n); - /* Für jeden Samen Talent*5% Erfolgschance. */ + /* F�r jeden Samen Talent*5% Erfolgschance. */ for (i = n; i > 0; i--) { if (rng_int() % 100 < skill * 5) planted++; @@ -2230,7 +2230,7 @@ static void breedtrees(unit * u, int raw) "unit region amount herb", u, r, planted, rtype)); } -/* züchte pferde */ +/* z�chte pferde */ static void breedhorses(unit * u) { int n, c, breed = 0; @@ -2283,7 +2283,7 @@ static void breed_cmd(unit * u, struct order *ord) return; } - /* züchte [] */ + /* z�chte [] */ (void)init_order(ord); s = gettoken(token, sizeof(token)); @@ -2549,7 +2549,7 @@ static void expandentertainment(region * r) m -= u->n; entertaining -= o->qty; - /* Nur soviel PRODUCEEXP wie auch tatsächlich gemacht wurde */ + /* Nur soviel PRODUCEEXP wie auch tats�chlich gemacht wurde */ produceexp(u, SK_ENTERTAINMENT, MIN(u->n, u->number)); add_income(u, IC_ENTERTAIN, o->qty, u->n); fset(u, UFL_LONGACTION | UFL_NOTMOVING); @@ -3121,7 +3121,7 @@ void produce(struct region *r) /* Entertainment (expandentertainment) und Besteuerung (expandtax) vor den * Befehlen, die den Bauern mehr Geld geben, damit man aus den Zahlen der - * letzten Runde berechnen kann, wieviel die Bauern für Unterhaltung + * letzten Runde berechnen kann, wieviel die Bauern f�r Unterhaltung * auszugeben bereit sind. */ if (entertaining) expandentertainment(r); @@ -3136,7 +3136,7 @@ void produce(struct region *r) /* An erster Stelle Kaufen (expandbuying), die Bauern so Geld bekommen, um * nachher zu beim Verkaufen (expandselling) den Spielern abkaufen zu - * können. */ + * k�nnen. */ if (buyorders) expandbuying(r, buyorders); diff --git a/src/economy.h b/src/economy.h index 5549e13cb..7b0eed8c9 100644 --- a/src/economy.h +++ b/src/economy.h @@ -56,6 +56,7 @@ extern "C" { enum { IC_WORK, IC_ENTERTAIN, IC_TAX, IC_TRADE, IC_TRADETAX, IC_STEAL, IC_MAGIC, IC_LOOT }; void maintain_buildings(struct region *r); + void make_item(struct unit * u, const struct item_type * itype, int want); int make_cmd(struct unit *u, struct order *ord); void split_allocations(struct region *r); int give_control_cmd(struct unit *u, struct order *ord); diff --git a/src/economy.test.c b/src/economy.test.c index 3c4a5f257..bee074714 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -341,12 +341,43 @@ static void test_income(CuTest *tc) test_cleanup(); } +static void test_make_item(CuTest *tc) { + unit *u; + struct item_type *itype; + const struct resource_type *rt_silver; + + test_setup(); + init_resources(); + rt_silver = get_resourcetype(R_SILVER); + itype = test_create_itemtype("log"); + u = test_create_unit(test_create_faction(0), test_create_region(0,0,0)); + make_item(u, itype, 1); + CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error_cannotmake")); + CuAssertIntEquals(tc, 0, get_item(u, itype)); + test_clear_messages(u->faction); + itype->construction = calloc(1, sizeof(construction)); + itype->construction->skill = SK_ALCHEMY; + itype->construction->minskill = 1; + itype->construction->maxsize = 1; + itype->construction->reqsize = 1; + itype->construction->materials = calloc(2, sizeof(requirement)); + itype->construction->materials[0].rtype = rt_silver; + itype->construction->materials[0].number = 1; + set_level(u, SK_ALCHEMY, 1); + set_item(u, rt_silver->itype, 1); + make_item(u, itype, 1); + CuAssertIntEquals(tc, 1, get_item(u, itype)); + CuAssertIntEquals(tc, 0, get_item(u, rt_silver->itype)); + test_cleanup(); +} + CuSuite *get_economy_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_give_control_building); SUITE_ADD_TEST(suite, test_give_control_ship); SUITE_ADD_TEST(suite, test_income); + SUITE_ADD_TEST(suite, test_make_item); SUITE_ADD_TEST(suite, test_steal_okay); SUITE_ADD_TEST(suite, test_steal_ocean); SUITE_ADD_TEST(suite, test_steal_nosteal); diff --git a/src/kernel/build.c b/src/kernel/build.c index 78bcd6b8f..88ab35fd2 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -397,7 +397,7 @@ static int required(int size, int msize, int maxneed) * braucht man required von maxneed resourcen */ { int used; - + assert(msize > 0); used = size * maxneed / msize; if (size * maxneed % msize) ++used; diff --git a/src/kernel/item.h b/src/kernel/item.h index c32f38057..39a2d0687 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -70,7 +70,7 @@ extern "C" { typedef char *(*rtype_name) (const struct resource_type * rtype, int flags); typedef struct resource_type { /* --- constants --- */ - char *_name; /* wie es heißt */ + char *_name; /* wie es hei�t */ unsigned int flags; /* --- functions --- */ rtype_uchange uchange; @@ -136,7 +136,7 @@ extern "C" { int weight; int capacity; struct construction *construction; - char *_appearance[2]; /* wie es für andere aussieht */ + char *_appearance[2]; /* wie es f�r andere aussieht */ /* --- functions --- */ bool(*canuse) (const struct unit * user, const struct item_type * itype); @@ -311,6 +311,8 @@ extern "C" { extern const struct potion_type *oldpotiontype[]; const struct resource_type *get_resourcetype(resource_t rt); + int get_item(const struct unit * u, const struct item_type *itype); + int set_item(struct unit * u, const struct item_type *itype, int value); int get_money(const struct unit *); int set_money(struct unit *, int); int change_money(struct unit *, int); From 5902a6922f06eae2d42591a71ff76b670cd146de Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 15 Feb 2017 20:50:45 +0100 Subject: [PATCH 2/6] BUG 2279: add a failing unit test. --- src/economy.test.c | 36 +++++++++++++++++++++++++++++++++++- src/kernel/resources.h | 16 +++++++--------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/economy.test.c b/src/economy.test.c index bee074714..ddb0cafbc 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -11,10 +11,12 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -345,11 +347,17 @@ static void test_make_item(CuTest *tc) { unit *u; struct item_type *itype; const struct resource_type *rt_silver; + resource_type *rtype; + attrib *a; + resource_limit *rdata; test_setup(); init_resources(); + + /* make items from other items (turn silver to stone) */ rt_silver = get_resourcetype(R_SILVER); - itype = test_create_itemtype("log"); + itype = test_create_itemtype("stone"); + rtype = itype->rtype; u = test_create_unit(test_create_faction(0), test_create_region(0,0,0)); make_item(u, itype, 1); CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error_cannotmake")); @@ -368,6 +376,32 @@ static void test_make_item(CuTest *tc) { make_item(u, itype, 1); CuAssertIntEquals(tc, 1, get_item(u, itype)); CuAssertIntEquals(tc, 0, get_item(u, rt_silver->itype)); + + /* make level-based raw materials, no materials used in construction */ + free(itype->construction->materials); + itype->construction->materials = 0; + rtype->flags |= RTF_LIMITED; + a = a_add(&rtype->attribs, a_new(&at_resourcelimit)); + rdata = (resource_limit *)a->data.v; + rdata->value = 0; + rmt_create(rtype, "stone"); + add_resource(u->region, 1, 300, 150, rtype); + u->region->resources->amount = 300; /* there are 300 stones at level 1 */ + set_level(u, SK_ALCHEMY, 10); + + make_item(u, itype, 10); + split_allocations(u->region); + CuAssertIntEquals(tc, 11, get_item(u, itype)); + CuAssertIntEquals(tc, 290, u->region->resources->amount); /* used 10 stones to make 10 stones */ + + rdata->modifiers = calloc(2, sizeof(resource_mod)); + rdata->modifiers[0].flags = RMF_SAVEMATERIAL; + rdata->modifiers[0].race = u->_race; + rdata->modifiers[0].value.f = (float)0.6; + make_item(u, itype, 10); + split_allocations(u->region); + CuAssertIntEquals(tc, 21, get_item(u, itype)); + CuAssertIntEquals(tc, 284, u->region->resources->amount); /* 60% saving = 6 stones make 10 stones */ test_cleanup(); } diff --git a/src/kernel/resources.h b/src/kernel/resources.h index 32c69036c..a1a7abd40 100644 --- a/src/kernel/resources.h +++ b/src/kernel/resources.h @@ -55,18 +55,16 @@ extern "C" { extern struct rawmaterial_type *rawmaterialtypes; - extern void update_resources(struct region *r); - extern void terraform_resources(struct region *r); - extern void read_resources(struct region *r); - extern void write_resources(struct region *r); - extern struct rawmaterial *rm_get(struct region *, + void update_resources(struct region *r); + void terraform_resources(struct region *r); + struct rawmaterial *rm_get(struct region *, const struct resource_type *); - extern struct rawmaterial_type *rmt_find(const char *str); - extern struct rawmaterial_type *rmt_get(const struct resource_type *); + struct rawmaterial_type *rmt_find(const char *str); + struct rawmaterial_type *rmt_get(const struct resource_type *); - extern void add_resource(struct region *r, int level, int base, int divisor, + void add_resource(struct region *r, int level, int base, int divisor, const struct resource_type *rtype); - extern struct rawmaterial_type *rmt_create(const struct resource_type *rtype, + struct rawmaterial_type *rmt_create(const struct resource_type *rtype, const char *name); #ifdef __cplusplus From 50083fc668641d6c232ce6b3958e16240c91a31d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 15 Feb 2017 21:16:54 +0100 Subject: [PATCH 3/6] BUG 2279: too many resources used. diddling the resource-save formula until test passes. --- src/economy.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/economy.c b/src/economy.c index 711a80d82..b38244ca8 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1038,8 +1038,6 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) static int required(int want, double save) { int req = (int)(want * save); - if (req < want * save) - ++req; return req; } @@ -1095,14 +1093,14 @@ leveled_allocation(const resource_type * rtype, region * r, allocation * alist) if (avail > 0) { int want = required(al->want - al->get, al->save); int x = avail * want / nreq; - /* Wenn Rest, dann w�rfeln, ob ich was bekomme: */ - if (rng_int() % nreq < (avail * want) % nreq) - ++x; + int r = (avail * want) % nreq; + /* Wenn Rest, dann wuerfeln, ob ich etwas bekomme: */ + if (r > 0 && rng_int() % nreq < r) ++x; avail -= x; use += x; nreq -= want; need -= x; - al->get = MIN(al->want, al->get + (int)(x / al->save)); + al->get = MIN(al->want, al->get + (int)(1 + x / al->save)); } } if (use) { From 20ff8981df584330e1cc9d3f29811903dcba961b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 15 Feb 2017 09:30:36 +0100 Subject: [PATCH 4/6] trying to extract allocation modifiers into a separate function --- src/economy.c | 80 ++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 45 deletions(-) diff --git a/src/economy.c b/src/economy.c index b38244ca8..abbf28a02 100644 --- a/src/economy.c +++ b/src/economy.c @@ -883,6 +883,32 @@ enum { AFL_LOWSKILL = 1 << 1 }; +struct message * get_modifiers(unit *u, const resource_mod *mod, double *savep, int *skillp) { + struct building *b = inside_building(u); + const struct building_type *btype = building_is_active(b) ? b->type : NULL; + double save = 1.0; + int skill = 0; + + for (; mod->flags != 0; ++mod) { + if (mod->btype == NULL || mod->btype == btype) { + if (mod->flags & RMF_REQUIREDBUILDING) { + return msg_error(u, u->thisorder, 104);; + } + if (mod->race == NULL || mod->race == u_race(u)) { + if (mod->flags & RMF_SAVEMATERIAL) { + save *= mod->value.f; + } + if (mod->flags & RMF_SKILL) { + skill += mod->value.i; + } + } + } + } + *skillp = skill; + *savep = save; + return NULL; +} + static void allocate_resource(unit * u, const resource_type * rtype, int want) { const item_type *itype = resource2item(rtype); @@ -893,7 +919,8 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) attrib *a = a_find(rtype->attribs, &at_resourcelimit); resource_limit *rdata = (resource_limit *)a->data.v; const resource_type *rring; - int amount, skill; + int amount, skill, skill_mod; + double save_mod; /* momentan kann man keine ressourcen abbauen, wenn man daf�r * Materialverbrauch hat: */ @@ -915,16 +942,11 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) } if (rdata->modifiers) { - resource_mod *mod = rdata->modifiers; - for (; mod->flags != 0; ++mod) { - if (mod->flags & RMF_REQUIREDBUILDING) { - struct building *b = inside_building(u); - const struct building_type *btype = building_is_active(b) ? b->type : NULL; - if (mod->btype && mod->btype != btype) { - cmistake(u, u->thisorder, 104, MSG_PRODUCE); - return; - } - } + message *msg = get_modifiers(u, rdata->modifiers, &save_mod, &skill_mod); + if (msg) { + ADDMSG(&u->faction->msgs, msg); + msg_release(msg); + return; } } @@ -962,23 +984,7 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) itype->rtype)); return; } - else { - struct building *b = inside_building(u); - const struct building_type *btype = building_is_active(b) ? b->type : NULL; - - if (rdata->modifiers) { - resource_mod *mod = rdata->modifiers; - for (; mod->flags != 0; ++mod) { - if (mod->flags & RMF_SKILL) { - if (mod->btype == NULL || mod->btype == btype) { - if (mod->race == NULL || mod->race == u_race(u)) { - skill += mod->value.i; - } - } - } - } - } - } + skill += skill_mod; amount = skill * u->number; /* nun ist amount die Gesamtproduktion der Einheit (in punkten) */ @@ -1013,26 +1019,10 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) } al = new_allocation(); al->want = amount; - al->save = 1.0; + al->save = save_mod; al->next = alist->data; al->unit = u; alist->data = al; - - if (rdata->modifiers) { - struct building *b = inside_building(u); - const struct building_type *btype = building_is_active(b) ? b->type : NULL; - - resource_mod *mod = rdata->modifiers; - for (; mod->flags != 0; ++mod) { - if (mod->flags & RMF_SAVEMATERIAL) { - if (mod->btype == NULL || mod->btype == btype) { - if (mod->race == NULL || mod->race == u_race(u)) { - al->save *= mod->value.f; - } - } - } - } - } } static int required(int want, double save) From a5dfe12d48cc147f8ecbbc6e7087c231581fd6dd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 16 Feb 2017 19:38:09 +0100 Subject: [PATCH 5/6] initialize variable --- src/economy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/economy.c b/src/economy.c index abbf28a02..df01f3b45 100644 --- a/src/economy.c +++ b/src/economy.c @@ -919,8 +919,8 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) attrib *a = a_find(rtype->attribs, &at_resourcelimit); resource_limit *rdata = (resource_limit *)a->data.v; const resource_type *rring; - int amount, skill, skill_mod; - double save_mod; + int amount, skill, skill_mod = 0; + double save_mod = 1.0; /* momentan kann man keine ressourcen abbauen, wenn man daf�r * Materialverbrauch hat: */ From a624915a0634ef1ac731c6c12e99242e25609a3d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 16 Feb 2017 20:26:34 +0100 Subject: [PATCH 6/6] error message if building is required. was broken in recent commit. also fix reference counts. --- src/economy.c | 6 ++---- src/economy.test.c | 7 +++++++ src/kernel/messages.c | 2 -- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/economy.c b/src/economy.c index df01f3b45..4c54cb5da 100644 --- a/src/economy.c +++ b/src/economy.c @@ -891,9 +891,6 @@ struct message * get_modifiers(unit *u, const resource_mod *mod, double *savep, for (; mod->flags != 0; ++mod) { if (mod->btype == NULL || mod->btype == btype) { - if (mod->flags & RMF_REQUIREDBUILDING) { - return msg_error(u, u->thisorder, 104);; - } if (mod->race == NULL || mod->race == u_race(u)) { if (mod->flags & RMF_SAVEMATERIAL) { save *= mod->value.f; @@ -902,6 +899,8 @@ struct message * get_modifiers(unit *u, const resource_mod *mod, double *savep, skill += mod->value.i; } } + } else if (mod->flags & RMF_REQUIREDBUILDING) { + return msg_error(u, u->thisorder, 104); } } *skillp = skill; @@ -945,7 +944,6 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) message *msg = get_modifiers(u, rdata->modifiers, &save_mod, &skill_mod); if (msg) { ADDMSG(&u->faction->msgs, msg); - msg_release(msg); return; } } diff --git a/src/economy.test.c b/src/economy.test.c index ddb0cafbc..7101d859a 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -402,6 +402,13 @@ static void test_make_item(CuTest *tc) { split_allocations(u->region); CuAssertIntEquals(tc, 21, get_item(u, itype)); CuAssertIntEquals(tc, 284, u->region->resources->amount); /* 60% saving = 6 stones make 10 stones */ + + rdata->modifiers[0].flags = RMF_REQUIREDBUILDING; + rdata->modifiers[0].race = NULL; + rdata->modifiers[0].btype = bt_get_or_create("mine"); + make_item(u, itype, 10); + CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error104")); + test_cleanup(); } diff --git a/src/kernel/messages.c b/src/kernel/messages.c index cb859df96..f74e9c0d7 100644 --- a/src/kernel/messages.c +++ b/src/kernel/messages.c @@ -270,8 +270,6 @@ void syntax_error(const struct unit *u, struct order *ord) ADDMSG(&u->faction->msgs, result); } -extern unsigned int new_hashstring(const char *s); - void free_messagelist(mlist *msgs) { struct mlist **mlistptr;