forked from github/server
commit
9aca86ec8b
|
@ -58,7 +58,7 @@ fi
|
|||
cat >| $BUILD/config.cmake <<HEREDOC
|
||||
SET (ERESSEA_DB "$ERESSEA_DB" CACHE STRING "Database driver")
|
||||
SET (LUA_DIR "$LUA_DIR" CACHE PATH "Lua root path")
|
||||
SET (CMAKE_BUILD_TYPE "$BUILD" FORCE)
|
||||
SET (CMAKE_BUILD_TYPE "$BUILD" CACHE STRING "")
|
||||
SET (CMAKE_INSTALL_PREFIX "$DEST" CACHE PATH "")
|
||||
SET (CMAKE_LIBRARY_PATH "$LIBRARY_PATH" CACHE PATH "")
|
||||
SET (CMAKE_PREFIX_PATH "$PREFIX_PATH" CACHE PATH "")
|
||||
|
|
|
@ -1568,7 +1568,7 @@ report_computer(const char *filename, report_context * ctx, const char *bom)
|
|||
}
|
||||
fprintf(F, "%d;age\n", f->age);
|
||||
fprintf(F, "%d;Optionen\n", f->options);
|
||||
if (f->options & want(O_SCORE) && f->age > DISPLAYSCORE) {
|
||||
if (f->options & WANT_OPTION(O_SCORE) && f->age > DISPLAYSCORE) {
|
||||
char score[32];
|
||||
write_score(score, sizeof(score), f->score);
|
||||
fprintf(F, "%s;Punkte\n", score);
|
||||
|
@ -1615,7 +1615,7 @@ report_computer(const char *filename, report_context * ctx, const char *bom)
|
|||
print_items(F, f->items, f->locale);
|
||||
fputs("OPTIONEN\n", F);
|
||||
for (i = 0; i != MAXOPTIONS; ++i) {
|
||||
int flag = want(i);
|
||||
int flag = WANT_OPTION(i);
|
||||
if (options[i]) {
|
||||
fprintf(F, "%d;%s\n", (f->options & flag) ? 1 : 0, options[i]);
|
||||
}
|
||||
|
|
278
src/economy.c
278
src/economy.c
|
@ -88,7 +88,7 @@ static econ_request entertainers[1024];
|
|||
static econ_request *nextentertainer;
|
||||
static int entertaining;
|
||||
|
||||
static econ_request *g_requests;
|
||||
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,31 +161,33 @@ 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;
|
||||
free_order(requests->ord);
|
||||
free(requests);
|
||||
requests = req;
|
||||
}
|
||||
return norders;
|
||||
}
|
||||
|
||||
static unsigned int expandorders(region * r, econ_request * requests) {
|
||||
|
@ -342,7 +344,7 @@ static int do_recruiting(recruitment * recruits, int available)
|
|||
if (number > afford) number = afford;
|
||||
}
|
||||
if (u->number + number > UNIT_MAXSIZE) {
|
||||
ADDMSG(&u->faction->msgs, msg_feedback(u, req->ord, "error_unit_size",
|
||||
ADDMSG(&u->faction->msgs, msg_feedback(u, req->type.recruit.ord, "error_unit_size",
|
||||
"maxsize", UNIT_MAXSIZE));
|
||||
number = UNIT_MAXSIZE - u->number;
|
||||
assert(number >= 0);
|
||||
|
@ -377,7 +379,6 @@ void free_recruitments(recruitment * recruits)
|
|||
while (rec->requests) {
|
||||
econ_request *req = rec->requests;
|
||||
rec->requests = req->next;
|
||||
free_order(req->ord);
|
||||
free(req);
|
||||
}
|
||||
free(rec);
|
||||
|
@ -555,7 +556,7 @@ static void recruit(unit * u, struct order *ord, econ_request ** recruitorders)
|
|||
o = (econ_request *)calloc(1, sizeof(econ_request));
|
||||
o->qty = n;
|
||||
o->unit = u;
|
||||
o->ord = copy_order(ord);
|
||||
o->type.recruit.ord = ord;
|
||||
addlist(recruitorders, o);
|
||||
}
|
||||
|
||||
|
@ -1477,54 +1478,54 @@ static void expandbuying(region * r, econ_request * buyorders)
|
|||
* G<EFBFBD>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.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<EFBFBD> gemacht werden, weil der Preis st<EFBFBD>ndig sinkt,
|
||||
* man sich also das verdiente Geld und die verkauften Produkte separat
|
||||
* merken mu<EFBFBD>. */
|
||||
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<EFBFBD> gemacht werden, weil der Preis st<EFBFBD>ndig sinkt,
|
||||
* man sich also das verdiente Geld und die verkauften Produkte separat
|
||||
* merken mu<EFBFBD>. */
|
||||
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<EFBFBD>r das Produkt um den Faktor 1. Der Z<EFBFBD>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<EFBFBD>r das Produkt um den Faktor 1. Der Z<EFBFBD>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);
|
||||
|
@ -1654,7 +1655,7 @@ static void buy(unit * u, econ_request ** buyorders, struct order *ord)
|
|||
return;
|
||||
}
|
||||
o = (econ_request *)calloc(1, sizeof(econ_request));
|
||||
o->type.ltype = ltype; /* sollte immer gleich sein */
|
||||
o->type.trade.ltype = ltype; /* sollte immer gleich sein */
|
||||
|
||||
o->unit = u;
|
||||
o->qty = n;
|
||||
|
@ -1752,79 +1753,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.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<65>hrt, denn die
|
||||
* Produkte k<EFBFBD>nnen auch als Steuern eingetrieben werden. In der Region
|
||||
* wurden Silberst<EFBFBD>cke gegen Luxusg<EFBFBD>ter des selben Wertes eingetauscht!
|
||||
* Falls mehr als max_products Kunden ein Produkt gekauft haben, sinkt
|
||||
* die Nachfrage f<EFBFBD>r das Produkt um 1. Der Z<EFBFBD>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<65>hrt, denn die
|
||||
* Produkte k<EFBFBD>nnen auch als Steuern eingetrieben werden. In der Region
|
||||
* wurden Silberst<EFBFBD>cke gegen Luxusg<EFBFBD>ter des selben Wertes eingetauscht!
|
||||
* Falls mehr als max_products Kunden ein Produkt gekauft haben, sinkt
|
||||
* die Nachfrage f<EFBFBD>r das Produkt um 1. Der Z<EFBFBD>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);
|
||||
|
@ -1970,7 +1969,7 @@ static bool sell(unit * u, econ_request ** sellorders, struct order *ord)
|
|||
/* Wenn andere Einheiten das selbe verkaufen, mu<6D> 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) {
|
||||
if (o->type.trade.ltype == ltype && o->unit->faction == u->faction) {
|
||||
int fpool =
|
||||
o->qty - get_pooled(o->unit, itype->rtype, GET_RESERVE, INT_MAX);
|
||||
if (fpool < 0) fpool = 0;
|
||||
|
@ -2010,7 +2009,7 @@ static bool sell(unit * u, econ_request ** sellorders, struct order *ord)
|
|||
o = (econ_request *)calloc(1, sizeof(econ_request));
|
||||
o->unit = u;
|
||||
o->qty = n;
|
||||
o->type.ltype = ltype;
|
||||
o->type.trade.ltype = ltype;
|
||||
addlist(sellorders, o);
|
||||
|
||||
return unlimited;
|
||||
|
@ -2518,8 +2517,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;
|
||||
}
|
||||
|
@ -2534,7 +2533,6 @@ static void expandloot(region * r, econ_request * lootorders)
|
|||
region_set_morale(r, m - 1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
for (u = r->units; u; u = u->next) {
|
||||
if (u->n >= 0) {
|
||||
add_income(u, IC_LOOT, u->wants, u->n);
|
||||
|
@ -2553,8 +2551,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);
|
||||
|
@ -2937,18 +2935,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<EFBFBD>nnen. */
|
||||
|
||||
if (buyorders)
|
||||
if (buyorders) {
|
||||
expandbuying(r, buyorders);
|
||||
free_requests(buyorders);
|
||||
}
|
||||
|
||||
if (sellorders) {
|
||||
int limit = rpeasants(r) / TRADE_FRACTION;
|
||||
|
@ -2956,13 +2959,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);
|
||||
|
|
|
@ -49,12 +49,18 @@ extern "C" {
|
|||
typedef struct econ_request {
|
||||
struct econ_request *next;
|
||||
struct unit *unit;
|
||||
struct order *ord;
|
||||
int qty;
|
||||
int no;
|
||||
union {
|
||||
bool goblin; /* stealing */
|
||||
const struct luxury_type *ltype; /* trading */
|
||||
struct {
|
||||
struct order *ord;
|
||||
} recruit;
|
||||
struct {
|
||||
int no;
|
||||
bool goblin; /* stealing */
|
||||
} steal;
|
||||
struct {
|
||||
const struct luxury_type *ltype; /* trading */
|
||||
} trade;
|
||||
} type;
|
||||
} econ_request;
|
||||
|
||||
|
@ -65,7 +71,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);
|
||||
|
|
|
@ -312,12 +312,21 @@ static void test_buy_cmd(CuTest *tc) {
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static void arm_unit(unit *u) {
|
||||
item_type *it_sword;
|
||||
|
||||
it_sword = test_create_itemtype("sword");
|
||||
new_weapontype(it_sword, 0, frac_zero, NULL, 0, 0, 0, SK_MELEE);
|
||||
i_change(&u->items, it_sword, u->number);
|
||||
set_level(u, SK_MELEE, 1);
|
||||
}
|
||||
|
||||
static void test_tax_cmd(CuTest *tc) {
|
||||
order *ord;
|
||||
faction *f;
|
||||
region *r;
|
||||
unit *u;
|
||||
item_type *sword, *silver;
|
||||
item_type *silver;
|
||||
econ_request *taxorders = 0;
|
||||
|
||||
test_setup();
|
||||
|
@ -337,10 +346,7 @@ static void test_tax_cmd(CuTest *tc) {
|
|||
|
||||
silver = get_resourcetype(R_SILVER)->itype;
|
||||
|
||||
sword = test_create_itemtype("sword");
|
||||
new_weapontype(sword, 0, frac_zero, NULL, 0, 0, 0, SK_MELEE);
|
||||
i_change(&u->items, sword, 1);
|
||||
set_level(u, SK_MELEE, 1);
|
||||
arm_unit(u);
|
||||
|
||||
tax_cmd(u, ord, &taxorders);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error_no_tax_skill"));
|
||||
|
@ -692,6 +698,49 @@ static void test_modify_production(CuTest *tc) {
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_loot(CuTest *tc) {
|
||||
unit *u;
|
||||
faction *f;
|
||||
item_type *it_silver;
|
||||
|
||||
test_setup();
|
||||
setup_production();
|
||||
it_silver = test_create_silver();
|
||||
config_set("rules.enable_loot", "1");
|
||||
u = test_create_unit(f = test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||
u->thisorder = create_order(K_LOOT, f->locale, NULL);
|
||||
produce(u->region);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error48")); /* unit is unarmed */
|
||||
test_clear_messages(f);
|
||||
arm_unit(u);
|
||||
produce(u->region);
|
||||
CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "income")); /* unit is unarmed */
|
||||
CuAssertIntEquals(tc, 2 * TAXFRACTION, i_get(u->items, it_silver));
|
||||
CuAssertIntEquals(tc, UFL_LONGACTION | UFL_NOTMOVING, fval(u, UFL_LONGACTION | UFL_NOTMOVING));
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_expand_production(CuTest *tc) {
|
||||
econ_request *orders;
|
||||
econ_request **results = NULL;
|
||||
region *r;
|
||||
unit *u;
|
||||
|
||||
test_setup();
|
||||
orders = calloc(1, sizeof(econ_request));
|
||||
orders->qty = 2;
|
||||
orders->unit = u = test_create_unit(test_create_faction(NULL), r = test_create_region(0, 0, NULL));
|
||||
orders->next = NULL;
|
||||
|
||||
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);
|
||||
CuAssertIntEquals(tc, 0, u->n);
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
CuSuite *get_economy_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
@ -711,5 +760,7 @@ CuSuite *get_economy_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_trade_insect);
|
||||
SUITE_ADD_TEST(suite, test_maintain_buildings);
|
||||
SUITE_ADD_TEST(suite, test_recruit);
|
||||
SUITE_ADD_TEST(suite, test_loot);
|
||||
SUITE_ADD_TEST(suite, test_expand_production);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -253,8 +253,9 @@ faction *addfaction(const char *email, const char *password,
|
|||
ADDMSG(&f->msgs, msg_message("changepasswd", "value", password));
|
||||
|
||||
f->options =
|
||||
want(O_REPORT) | want(O_ZUGVORLAGE) | want(O_COMPUTER) | want(O_COMPRESS) |
|
||||
want(O_ADRESSEN) | want(O_STATISTICS);
|
||||
WANT_OPTION(O_REPORT) | WANT_OPTION(O_ZUGVORLAGE) |
|
||||
WANT_OPTION(O_COMPUTER) | WANT_OPTION(O_COMPRESS) |
|
||||
WANT_OPTION(O_ADRESSEN) | WANT_OPTION(O_STATISTICS);
|
||||
|
||||
f->no = unused_faction_id();
|
||||
if (rule_region_owners()) {
|
||||
|
|
|
@ -99,7 +99,7 @@ extern "C" {
|
|||
|
||||
extern struct faction *factions;
|
||||
|
||||
#define want(option) (1<<option)
|
||||
#define WANT_OPTION(option) (1<<option)
|
||||
|
||||
void fhash(struct faction *f);
|
||||
void funhash(struct faction *f);
|
||||
|
|
|
@ -321,23 +321,48 @@ static void writeorder(gamedata *data, const struct order *ord,
|
|||
WRITE_STR(data->store, obuf);
|
||||
}
|
||||
|
||||
static void read_skill(gamedata *data, skill *sv) {
|
||||
int val;
|
||||
READ_INT(data->store, &val);
|
||||
assert(val < MAXSKILLS);
|
||||
sv->id = (skill_t)val;
|
||||
if (sv->id != NOSKILL) {
|
||||
READ_INT(data->store, &val);
|
||||
assert(val < CHAR_MAX);
|
||||
sv->old = sv->level = val;
|
||||
READ_INT(data->store, &val);
|
||||
assert(val < CHAR_MAX);
|
||||
sv->weeks = val;
|
||||
}
|
||||
}
|
||||
|
||||
static int skill_cmp(const void *a, const void *b) {
|
||||
const skill * sa = (const skill *)a;
|
||||
const skill * sb = (const skill *)b;
|
||||
return sa->id - sb->id;
|
||||
}
|
||||
|
||||
static void read_skills(gamedata *data, unit *u)
|
||||
{
|
||||
if (data->version < SKILLSORT_VERSION) {
|
||||
skill skills[MAXSKILLS], *sv = skills;
|
||||
|
||||
u->skill_size = 0;
|
||||
for (;;) {
|
||||
int n = NOSKILL, level, weeks;
|
||||
skill_t sk;
|
||||
READ_INT(data->store, &n);
|
||||
sk = (skill_t)n;
|
||||
if (sk == NOSKILL) break;
|
||||
READ_INT(data->store, &level);
|
||||
READ_INT(data->store, &weeks);
|
||||
if (level) {
|
||||
skill *sv = add_skill(u, sk);
|
||||
sv->level = sv->old = (unsigned char)level;
|
||||
sv->weeks = (unsigned char)weeks;
|
||||
read_skill(data, sv);
|
||||
if (sv->id == NOSKILL) break;
|
||||
if (sv->level > 0) {
|
||||
++sv;
|
||||
++u->skill_size;
|
||||
}
|
||||
}
|
||||
if (u->skill_size > 0) {
|
||||
size_t sz = u->skill_size * sizeof(skill);
|
||||
|
||||
qsort(skills, u->skill_size, sizeof(skill), skill_cmp);
|
||||
u->skills = malloc(sz);
|
||||
memcpy(u->skills, skills, sz);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
|
@ -345,12 +370,7 @@ static void read_skills(gamedata *data, unit *u)
|
|||
u->skills = malloc(sizeof(skill)*u->skill_size);
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
skill *sv = u->skills + i;
|
||||
int val;
|
||||
READ_INT(data->store, &val);
|
||||
sv->id = (skill_t)val;
|
||||
READ_INT(data->store, &sv->level);
|
||||
sv->old = sv->level;
|
||||
READ_INT(data->store, &sv->weeks);
|
||||
read_skill(data, sv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1051,14 +1071,14 @@ faction *read_faction(gamedata * data)
|
|||
READ_INT(data->store, &n);
|
||||
f->options = n;
|
||||
|
||||
n = want(O_REPORT) | want(O_COMPUTER);
|
||||
n = WANT_OPTION(O_REPORT) | WANT_OPTION(O_COMPUTER);
|
||||
if ((f->options & n) == 0) {
|
||||
/* Kein Report eingestellt, Fehler */
|
||||
f->options |= n;
|
||||
}
|
||||
if (data->version < JSON_REPORT_VERSION) {
|
||||
/* mistakes were made in the past*/
|
||||
f->options &= ~want(O_JSON);
|
||||
f->options &= ~WANT_OPTION(O_JSON);
|
||||
}
|
||||
read_allies(data, f);
|
||||
read_groups(data, f);
|
||||
|
@ -1119,7 +1139,7 @@ void write_faction(gamedata *data, const faction * f)
|
|||
WRITE_INT(data->store, ur->y);
|
||||
}
|
||||
WRITE_SECTION(data->store);
|
||||
WRITE_INT(data->store, f->options & ~want(O_DEBUG));
|
||||
WRITE_INT(data->store, f->options & ~WANT_OPTION(O_DEBUG));
|
||||
WRITE_SECTION(data->store);
|
||||
|
||||
for (sf = f->allies; sf; sf = sf->next) {
|
||||
|
|
|
@ -619,7 +619,8 @@ static void test_shipspeed_max_range(CuTest *tc) {
|
|||
CuAssertIntEquals_Msg(tc, "skill bonus from movement.shipspeed.skillbonus", 3, shipspeed(sh, cap));
|
||||
|
||||
set_level(cap, SK_SAILING, stype->cptskill + 15);
|
||||
set_level(crew, SK_SAILING, (stype->sumskill - stype->cptskill) * 15);
|
||||
scale_number(crew, 15);
|
||||
set_level(crew, SK_SAILING, stype->sumskill - stype->cptskill);
|
||||
CuAssertIntEquals_Msg(tc, "skill-bonus cannot exceed max_range", 4, shipspeed(sh, cap));
|
||||
test_teardown();
|
||||
}
|
||||
|
|
|
@ -26,10 +26,10 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
typedef struct skill {
|
||||
skill_t id;
|
||||
int level;
|
||||
int weeks;
|
||||
int old;
|
||||
skill_t id : 8;
|
||||
int level : 8;
|
||||
int weeks : 8;
|
||||
int old : 8;
|
||||
} skill;
|
||||
|
||||
typedef int(*skillmod_fun) (const struct unit *, const struct region *,
|
||||
|
|
|
@ -795,6 +795,7 @@ void set_level(unit * u, skill_t sk, int value)
|
|||
skill *sv = u->skills;
|
||||
|
||||
assert(sk != SK_MAGIC || !u->faction || u->number == 1 || fval(u->faction, FFL_NPC));
|
||||
assert(value <= CHAR_MAX && value >= CHAR_MIN);
|
||||
if (!skill_enabled(sk))
|
||||
return;
|
||||
|
||||
|
|
10
src/report.c
10
src/report.c
|
@ -2048,7 +2048,7 @@ report_plaintext(const char *filename, report_context * ctx,
|
|||
attrib *a;
|
||||
message *m;
|
||||
unsigned char op;
|
||||
int maxh, bytes, ix = want(O_STATISTICS);
|
||||
int maxh, bytes, ix = WANT_OPTION(O_STATISTICS);
|
||||
int wants_stats = (f->options & ix);
|
||||
FILE *F = fopen(filename, "w");
|
||||
stream strm = { 0 }, *out = &strm;
|
||||
|
@ -2098,18 +2098,18 @@ report_plaintext(const char *filename, report_context * ctx,
|
|||
centre(out, buf, true);
|
||||
}
|
||||
}
|
||||
if ((f->options & want(O_COMPUTER)) == 0) {
|
||||
if ((f->options & WANT_OPTION(O_COMPUTER)) == 0) {
|
||||
const char *s;
|
||||
s = locale_getstring(f->locale, "newbie_info_cr");
|
||||
if (s) {
|
||||
newline(out);
|
||||
centre(out, s, true);
|
||||
}
|
||||
f->options |= want(O_COMPUTER);
|
||||
f->options |= WANT_OPTION(O_COMPUTER);
|
||||
}
|
||||
}
|
||||
newline(out);
|
||||
if (f->options & want(O_SCORE) && f->age > DISPLAYSCORE) {
|
||||
if (f->options & WANT_OPTION(O_SCORE) && f->age > DISPLAYSCORE) {
|
||||
char score[32], avg[32];
|
||||
write_score(score, sizeof(score), f->score);
|
||||
write_score(avg, sizeof(avg), average_score_of_age(f->age, f->age / 24 + 1));
|
||||
|
@ -2164,7 +2164,7 @@ report_plaintext(const char *filename, report_context * ctx,
|
|||
if (wrptr(&bufp, &size, bytes) != 0)
|
||||
WARN_STATIC_BUFFER();
|
||||
for (op = 0; op != MAXOPTIONS; op++) {
|
||||
if (f->options & want(op) && options[op]) {
|
||||
if (f->options & WANT_OPTION(op) && options[op]) {
|
||||
bytes = (int)str_strlcpy(bufp, " ", size);
|
||||
if (wrptr(&bufp, &size, bytes) != 0)
|
||||
WARN_STATIC_BUFFER();
|
||||
|
|
|
@ -928,7 +928,7 @@ spskill(char *buffer, size_t size, const struct locale * lang,
|
|||
if (!u->number)
|
||||
return 0;
|
||||
if (sv->level <= 0) {
|
||||
if (sv->old <= 0 || (u->faction->options & want(O_SHOWSKCHANGE)) == 0) {
|
||||
if (sv->old <= 0 || (u->faction->options & WANT_OPTION(O_SHOWSKCHANGE)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -964,7 +964,7 @@ spskill(char *buffer, size_t size, const struct locale * lang,
|
|||
if (wrptr(&bufp, &size, snprintf(bufp, size, "%d", effsk)) != 0)
|
||||
WARN_STATIC_BUFFER();
|
||||
|
||||
if (u->faction->options & want(O_SHOWSKCHANGE)) {
|
||||
if (u->faction->options & WANT_OPTION(O_SHOWSKCHANGE)) {
|
||||
int oldeff = 0;
|
||||
int diff;
|
||||
|
||||
|
|
20
src/steal.c
20
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].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);
|
||||
}
|
||||
|
@ -237,8 +237,8 @@ void steal_cmd(unit * u, struct order *ord, econ_request ** stealorders)
|
|||
o = (econ_request *)calloc(1, sizeof(econ_request));
|
||||
o->unit = u;
|
||||
o->qty = 1; /* Betrag steht in u->wants */
|
||||
o->no = u2->no;
|
||||
o->type.goblin = goblin; /* Merken, wenn Goblin-Spezialklau */
|
||||
o->type.steal.no = u2->no;
|
||||
o->type.steal.goblin = goblin; /* Merken, wenn Goblin-Spezialklau */
|
||||
o->next = *stealorders;
|
||||
*stealorders = o;
|
||||
|
||||
|
|
|
@ -828,6 +828,7 @@ void learn_skill(unit *u, skill_t sk, int days) {
|
|||
int leveldays = STUDYDAYS * u->number;
|
||||
int weeks = 0;
|
||||
|
||||
assert(sk >= 0 && sk < MAXSKILLS);
|
||||
if (inject_learn_fun) {
|
||||
inject_learn_fun(u, sk, days);
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue