fix bug #1795: demon recruitment limit

This commit is contained in:
Steffen Mecke 2012-07-26 10:35:09 +02:00
parent 69a51c4b2c
commit 379e1a8f3f
2 changed files with 52 additions and 7 deletions

View File

@ -1299,3 +1299,38 @@ function test_bug_1870_leave_enter_e3()
process_orders() process_orders()
assert_equal(u1.building.id, mine.id) assert_equal(u1.building.id, mine.id)
end end
function test_bug_1795_limit()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "human", "de")
local u1 = one_unit(r,f)
u1:add_item("money", 100000000)
u1:add_order("REKRUTIEREN 9999")
r:set_resource("peasant", 2000) -- no fractional growth!
local peasants = r:get_resource("peasant")
local limit,frac = math.modf(peasants/40) -- one day this should be a parameter
local growth = peasants * 0.001
process_orders()
assert_equal(limit+1, u1.number, u1.number .. "!=" .. (limit+1))
assert_equal(peasants+growth-limit, r:get_resource("peasant"))
end
function test_bug_1795_demons()
local r = region.create(0, 0, "plain")
local f = faction.create("noreply@eressea.de", "demon", "de")
local u1 = one_unit(r,f)
r:set_resource("peasant", 2000)
local peasants = r:get_resource("peasant")
local limit,frac = math.modf(peasants/40)
local growth = peasants * 0.001
u1:add_item("money", 100000000)
u1:add_order("REKRUTIEREN 9999")
process_orders()
assert_equal(limit+1, u1.number, u1.number .. "!=" .. (limit+1))
assert_equal(peasants+growth, r:get_resource("peasant"))
end

View File

@ -215,6 +215,9 @@ typedef struct recruitment {
int total, assigned; int total, assigned;
} recruitment; } recruitment;
/** Creates a list of recruitment structs, one for each faction. Adds every quantifyable request
* to the faction's struct and to total.
*/
static recruitment *select_recruitment(request ** rop, static recruitment *select_recruitment(request ** rop,
int (*quantify) (const struct race *, int), int *total) int (*quantify) (const struct race *, int), int *total)
{ {
@ -292,14 +295,14 @@ static int any_recruiters(const struct race *rc, int qty)
return (int)(qty * 2 * rc->recruit_multi); return (int)(qty * 2 * rc->recruit_multi);
} }
static int peasant_recruiters(const struct race *rc, int qty) /*static int peasant_recruiters(const struct race *rc, int qty)
{ {
if (rc->ec_flags & ECF_REC_ETHEREAL) if (rc->ec_flags & ECF_REC_ETHEREAL)
return -1; return -1;
if (rc->ec_flags & ECF_REC_HORSES) if (rc->ec_flags & ECF_REC_HORSES)
return -1; return -1;
return (int)(qty * 2 * rc->recruit_multi); return (int)(qty * 2 * rc->recruit_multi);
} }*/
static int horse_recruiters(const struct race *rc, int qty) static int horse_recruiters(const struct race *rc, int qty)
{ {
@ -315,10 +318,12 @@ static int do_recruiting(recruitment * recruits, int available)
recruitment *rec; recruitment *rec;
int recruited = 0; int recruited = 0;
/* try to assign recruits to factions fairly */
while (available > 0) { while (available > 0) {
int n = 0; int n = 0;
int rest, mintotal = INT_MAX; int rest, mintotal = INT_MAX;
/* find smallest request */
for (rec = recruits; rec != NULL; rec = rec->next) { for (rec = recruits; rec != NULL; rec = rec->next) {
int want = rec->total - rec->assigned; int want = rec->total - rec->assigned;
if (want > 0) { if (want > 0) {
@ -334,6 +339,8 @@ static int do_recruiting(recruitment * recruits, int available)
} }
rest = available - mintotal * n; rest = available - mintotal * n;
/* assign size of smallest request for everyone if possible; in the end roll dice to assign
* small rest */
for (rec = recruits; rec != NULL; rec = rec->next) { for (rec = recruits; rec != NULL; rec = rec->next) {
int want = rec->total - rec->assigned; int want = rec->total - rec->assigned;
@ -350,6 +357,7 @@ static int do_recruiting(recruitment * recruits, int available)
} }
} }
/* do actual recruiting */
for (rec = recruits; rec != NULL; rec = rec->next) { for (rec = recruits; rec != NULL; rec = rec->next) {
request *req; request *req;
int get = rec->assigned; int get = rec->assigned;
@ -365,8 +373,6 @@ static int do_recruiting(recruitment * recruits, int available)
int afford = get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, int afford = get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT,
number * rc->recruitcost) / rc->recruitcost; number * rc->recruitcost) / rc->recruitcost;
number = MIN(number, afford); number = MIN(number, afford);
use_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT,
rc->recruitcost * number);
} }
if (u->number + number > UNIT_MAXSIZE) { 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->ord, "error_unit_size",
@ -374,6 +380,10 @@ static int do_recruiting(recruitment * recruits, int available)
number = UNIT_MAXSIZE - u->number; number = UNIT_MAXSIZE - u->number;
assert(number >= 0); assert(number >= 0);
} }
if (rc->recruitcost) {
use_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT,
rc->recruitcost * number);
}
add_recruits(u, number, req->qty); add_recruits(u, number, req->qty);
dec = (int)(number * multi); dec = (int)(number * multi);
if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) {
@ -449,7 +459,7 @@ static void expandrecruit(region * r, request * recruitorders)
} }
/* peasant limited: */ /* peasant limited: */
recruits = select_recruitment(&recruitorders, peasant_recruiters, &orc_total); recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total);
if (recruits) { if (recruits) {
int orc_recruited, orc_peasants = rpeasants(r) * 2; int orc_recruited, orc_peasants = rpeasants(r) * 2;
int orc_frac = orc_peasants / RECRUITFRACTION; /* anzahl orks. 2 ork = 1 bauer */ int orc_frac = orc_peasants / RECRUITFRACTION; /* anzahl orks. 2 ork = 1 bauer */
@ -464,10 +474,10 @@ static void expandrecruit(region * r, request * recruitorders)
/* no limit: */ /* no limit: */
recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total); recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total);
if (recruits) { if (recruits) {
int recruited, peasants = rpeasants(r); int recruited, peasants = rpeasants(r) * 2;
recruited = do_recruiting(recruits, INT_MAX); recruited = do_recruiting(recruits, INT_MAX);
if (recruited > 0) { if (recruited > 0) {
rsetpeasants(r, peasants - recruited / 2); rsetpeasants(r, (peasants - recruited) / 2);
} }
free_recruitments(recruits); free_recruitments(recruits);
} }