forked from github/server
Refactor the wage function for readability.
Add a test for wages at different castle sizes.
This commit is contained in:
parent
6868cbb928
commit
8c62bd95cd
|
@ -1363,9 +1363,11 @@ static void cr_output_region(FILE * F, report_context * ctx, region * r)
|
|||
fprintf(F, "%d;Rekruten\n", rpeasants(r) / RECRUITFRACTION);
|
||||
}
|
||||
if (max_production(r)) {
|
||||
int p_wage = wage(r, NULL, NULL, turn + 1);
|
||||
/* Im CR steht der Bauernlohn, der bei Trauer nur 10 ist */
|
||||
bool mourn = is_mourning(r, turn);
|
||||
int p_wage = peasant_wage(r, mourn);
|
||||
fprintf(F, "%d;Lohn\n", p_wage);
|
||||
if (is_mourning(r, turn + 1)) {
|
||||
if (mourn) {
|
||||
fputs("1;mourning\n", F);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1993,7 +1993,8 @@ expandwork(region * r, econ_request * work_begin, econ_request * work_end, int m
|
|||
/* n: verbleibende Einnahmen */
|
||||
/* fishes: maximale Arbeiter */
|
||||
int jobs = maxwork;
|
||||
int p_wage = wage(r, NULL, NULL, turn);
|
||||
bool mourn = is_mourning(r, turn);
|
||||
int p_wage = peasant_wage(r, mourn);
|
||||
int money = rmoney(r);
|
||||
if (total > 0 && !rule_autowork()) {
|
||||
econ_request *o;
|
||||
|
@ -2017,7 +2018,7 @@ expandwork(region * r, econ_request * work_begin, econ_request * work_end, int m
|
|||
|
||||
assert(workers >= 0);
|
||||
|
||||
u->n = workers * wage(u->region, u->faction, u_race(u), turn);
|
||||
u->n = workers * wage(u->region, u_race(u));
|
||||
|
||||
jobs -= workers;
|
||||
assert(jobs >= 0);
|
||||
|
@ -2061,7 +2062,7 @@ static int work_cmd(unit * u, order * ord, econ_request ** io_req)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
w = wage(r, u->faction, u_race(u), turn);
|
||||
w = wage(r, u_race(u));
|
||||
add_request(req++, ECON_WORK, u, ord, w * u->number);
|
||||
*io_req = req;
|
||||
return u->number;
|
||||
|
|
|
@ -495,20 +495,22 @@ extern struct attrib_type at_icastle;
|
|||
/** returns the building's build stage (NOT size in people).
|
||||
* only makes sense for castles or similar buildings with multiple
|
||||
* stages */
|
||||
int buildingeffsize(const building * b, int img)
|
||||
int buildingeffsize(const building * b, bool imaginary)
|
||||
{
|
||||
const struct building_type *btype = NULL;
|
||||
|
||||
if (b == NULL)
|
||||
return 0;
|
||||
|
||||
btype = b->type;
|
||||
if (img) {
|
||||
if (imaginary) {
|
||||
const attrib *a = a_find(b->attribs, &at_icastle);
|
||||
if (a) {
|
||||
btype = (const struct building_type *)a->data.v;
|
||||
}
|
||||
}
|
||||
else {
|
||||
btype = b->type;
|
||||
}
|
||||
return bt_effsize(btype, b, b->size);
|
||||
}
|
||||
|
||||
|
@ -518,7 +520,7 @@ int bt_effsize(const building_type * btype, const building * b, int bsize)
|
|||
bsize = adjust_size(b, bsize);
|
||||
}
|
||||
|
||||
if (btype->stages) {
|
||||
if (btype && btype->stages) {
|
||||
int n = 0;
|
||||
const building_stage *stage = btype->stages;
|
||||
do {
|
||||
|
@ -728,7 +730,7 @@ static const int wagetable[7][3] = {
|
|||
};
|
||||
|
||||
static int
|
||||
default_wage(const region * r, const faction * f, const race * rc, int in_turn)
|
||||
default_wage(const region * r, const race * rc)
|
||||
{
|
||||
building *b = largestbuilding(r, cmp_wage, false);
|
||||
int esize = 0;
|
||||
|
@ -739,27 +741,21 @@ default_wage(const region * r, const faction * f, const race * rc, int in_turn)
|
|||
esize = buildingeffsize(b, false);
|
||||
}
|
||||
|
||||
if (f != NULL) {
|
||||
if (rc != NULL) {
|
||||
static const struct race *rc_orc, *rc_snotling;
|
||||
static int rc_cache;
|
||||
int index = 0;
|
||||
if (rc == get_race(RC_ORC) || rc == get_race(RC_SNOTLING)) {
|
||||
if (rc_changed(&rc_cache)) {
|
||||
rc_orc = get_race(RC_ORC);
|
||||
rc_snotling = get_race(RC_SNOTLING);
|
||||
}
|
||||
if (rc == rc_orc || rc == rc_snotling) {
|
||||
index = 1;
|
||||
}
|
||||
wage = wagetable[esize][index];
|
||||
}
|
||||
else {
|
||||
if (is_mourning(r, in_turn)) {
|
||||
wage = 10;
|
||||
}
|
||||
else if (fval(r->terrain, SEA_REGION)) {
|
||||
wage = 11;
|
||||
}
|
||||
else {
|
||||
wage = wagetable[esize][2];
|
||||
}
|
||||
if (r->attribs && rule_blessed_harvest() == HARVEST_WORK) {
|
||||
/* E1 rules */
|
||||
wage += harvest_effect(r);
|
||||
}
|
||||
wage = wagetable[esize][2];
|
||||
}
|
||||
|
||||
if (r->attribs) {
|
||||
|
@ -767,6 +763,10 @@ default_wage(const region * r, const faction * f, const race * rc, int in_turn)
|
|||
curse *c;
|
||||
variant vm;
|
||||
|
||||
if (rule_blessed_harvest() & HARVEST_WORK) {
|
||||
/* In E3 */
|
||||
wage += harvest_effect(r);
|
||||
}
|
||||
/* Godcurse: Income -10 */
|
||||
vm = frac_make(wage, 1);
|
||||
|
||||
|
@ -786,31 +786,37 @@ default_wage(const region * r, const faction * f, const race * rc, int in_turn)
|
|||
}
|
||||
|
||||
static int
|
||||
minimum_wage(const region * r, const faction * f, const race * rc, int in_turn)
|
||||
minimum_wage(const region * r, const race * rc)
|
||||
{
|
||||
if (f && rc) {
|
||||
if (rc) {
|
||||
return rc->maintenance;
|
||||
}
|
||||
return default_wage(r, f, rc, in_turn);
|
||||
return default_wage(r, rc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt Arbeitslohn fuer entsprechende Rasse zurueck, oder fuer
|
||||
* die Bauern wenn f == NULL. */
|
||||
int wage(const region * r, const faction * f, const race * rc, int in_turn)
|
||||
* die Bauern wenn rc == NULL. */
|
||||
int wage(const region * r, const race * rc)
|
||||
{
|
||||
static int config;
|
||||
static int rule_wage;
|
||||
if (config_changed(&config)) {
|
||||
rule_wage = config_get_int("rules.wage.function", 1);
|
||||
}
|
||||
if (rule_wage==0) {
|
||||
if (rule_wage == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (rule_wage==1) {
|
||||
return default_wage(r, f, rc, in_turn);
|
||||
|
||||
if (rule_wage == 1) {
|
||||
return default_wage(r, rc);
|
||||
}
|
||||
return minimum_wage(r, f, rc, in_turn);
|
||||
return minimum_wage(r, rc);
|
||||
}
|
||||
|
||||
int peasant_wage(const struct region *r, bool mourn)
|
||||
{
|
||||
return mourn ? 10 : wage(r, NULL);
|
||||
}
|
||||
|
||||
int cmp_wage(const struct building *b, const building * a)
|
||||
|
|
|
@ -116,8 +116,8 @@ extern "C" {
|
|||
int id, int size, struct order *ord);
|
||||
bool building_finished(const struct building *b);
|
||||
|
||||
int wage(const struct region *r, const struct faction *f,
|
||||
const struct race *rc, int in_turn);
|
||||
int wage(const struct region *r, const struct race *rc);
|
||||
int peasant_wage(const struct region *r, bool mourn);
|
||||
|
||||
typedef int(*cmp_building_cb) (const struct building * b,
|
||||
const struct building * a);
|
||||
|
@ -130,7 +130,7 @@ extern "C" {
|
|||
int building_taxes(const building *b);
|
||||
|
||||
/* old functions, still in build.c: */
|
||||
int buildingeffsize(const building * b, int imaginary);
|
||||
int buildingeffsize(const building * b, bool imaginary);
|
||||
void bhash(struct building *b);
|
||||
void bunhash(struct building *b);
|
||||
int buildingcapacity(const struct building *b);
|
||||
|
|
|
@ -434,6 +434,80 @@ static void test_cmp_castle_size(CuTest *tc) {
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_wage(CuTest *tc) {
|
||||
region *r;
|
||||
building *b;
|
||||
building_type *btype;
|
||||
struct building_stage *stage;
|
||||
race *rc_orc, *rc_elf;
|
||||
test_setup();
|
||||
rc_orc = test_create_race("orc");
|
||||
rc_elf = test_create_race("elf");
|
||||
rc_elf->maintenance = 13;
|
||||
btype = test_create_buildingtype("castle");
|
||||
stage = btype->stages;
|
||||
stage->construction->maxsize = 2; /* site */
|
||||
stage = stage->next = calloc(1, sizeof(struct building_stage));
|
||||
stage->construction = calloc(1, sizeof(struct construction));
|
||||
stage->construction->maxsize = 8; /* tradepost */
|
||||
stage = stage->next = calloc(1, sizeof(struct building_stage));
|
||||
stage->construction = calloc(1, sizeof(struct construction));
|
||||
stage->construction->maxsize = 40; /* fortification */
|
||||
stage = stage->next = calloc(1, sizeof(struct building_stage));
|
||||
stage->construction = calloc(1, sizeof(struct construction));
|
||||
stage->construction->maxsize = 200; /* fortification */
|
||||
r = test_create_plain(0, 0);
|
||||
CuAssertIntEquals(tc, 10, wage(r, rc_elf));
|
||||
CuAssertIntEquals(tc, 10, wage(r, rc_orc));
|
||||
CuAssertIntEquals(tc, 11, peasant_wage(r, false));
|
||||
CuAssertIntEquals(tc, 10, peasant_wage(r, true));
|
||||
|
||||
b = test_create_building(r, btype);
|
||||
b->size = 1;
|
||||
CuAssertIntEquals(tc, 0, buildingeffsize(b, false));
|
||||
CuAssertIntEquals(tc, 10, wage(r, rc_elf));
|
||||
CuAssertIntEquals(tc, 10, wage(r, rc_orc));
|
||||
CuAssertIntEquals(tc, 11, peasant_wage(r, false));
|
||||
CuAssertIntEquals(tc, 10, peasant_wage(r, true));
|
||||
b->size = 2;
|
||||
CuAssertIntEquals(tc, 1, buildingeffsize(b, false));
|
||||
b->size = 9;
|
||||
CuAssertIntEquals(tc, 1, buildingeffsize(b, false));
|
||||
CuAssertIntEquals(tc, 10, wage(r, rc_elf));
|
||||
CuAssertIntEquals(tc, 10, wage(r, rc_orc));
|
||||
CuAssertIntEquals(tc, 11, peasant_wage(r, false));
|
||||
CuAssertIntEquals(tc, 10, peasant_wage(r, true));
|
||||
b->size = 10;
|
||||
CuAssertIntEquals(tc, 2, buildingeffsize(b, false));
|
||||
b->size = 49;
|
||||
CuAssertIntEquals(tc, 2, buildingeffsize(b, false));
|
||||
CuAssertIntEquals(tc, 11, wage(r, rc_elf));
|
||||
CuAssertIntEquals(tc, 11, wage(r, rc_orc));
|
||||
CuAssertIntEquals(tc, 12, peasant_wage(r, false));
|
||||
CuAssertIntEquals(tc, 10, peasant_wage(r, true));
|
||||
b->size = 50;
|
||||
CuAssertIntEquals(tc, 3, buildingeffsize(b, false));
|
||||
b->size = 249;
|
||||
CuAssertIntEquals(tc, 3, buildingeffsize(b, false));
|
||||
CuAssertIntEquals(tc, 12, wage(r, rc_elf));
|
||||
CuAssertIntEquals(tc, 11, wage(r, rc_orc));
|
||||
CuAssertIntEquals(tc, 13, peasant_wage(r, false));
|
||||
CuAssertIntEquals(tc, 10, peasant_wage(r, true));
|
||||
b->size = 250;
|
||||
CuAssertIntEquals(tc, 4, buildingeffsize(b, false));
|
||||
CuAssertIntEquals(tc, 13, wage(r, rc_elf));
|
||||
CuAssertIntEquals(tc, 12, wage(r, rc_orc));
|
||||
CuAssertIntEquals(tc, 14, peasant_wage(r, false));
|
||||
CuAssertIntEquals(tc, 10, peasant_wage(r, true));
|
||||
config_set_int("rules.wage.function", 1);
|
||||
CuAssertIntEquals(tc, 13, wage(r, rc_elf));
|
||||
config_set_int("rules.wage.function", 0);
|
||||
CuAssertIntEquals(tc, 0, wage(r, rc_elf));
|
||||
config_set_int("rules.wage.function", 2);
|
||||
CuAssertIntEquals(tc, rc_elf->maintenance, wage(r, rc_elf));
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_cmp_wage(CuTest *tc) {
|
||||
region *r;
|
||||
building *b1, *b2;
|
||||
|
@ -619,6 +693,7 @@ CuSuite *get_building_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_cmp_castle_size);
|
||||
SUITE_ADD_TEST(suite, test_cmp_taxes);
|
||||
SUITE_ADD_TEST(suite, test_cmp_wage);
|
||||
SUITE_ADD_TEST(suite, test_wage);
|
||||
SUITE_ADD_TEST(suite, test_cmp_current_owner);
|
||||
SUITE_ADD_TEST(suite, test_register_building);
|
||||
SUITE_ADD_TEST(suite, test_btype_defaults);
|
||||
|
|
|
@ -42,7 +42,7 @@ extern "C" {
|
|||
bool rule_stealth_anon(void); /* units can anonymize their faction, TARNE PARTEI [NICHT] */
|
||||
int rule_alliance_limit(void);
|
||||
int rule_faction_limit(void);
|
||||
#define HARVEST_WORK 0x00
|
||||
#define HARVEST_WORK 0x02
|
||||
#define HARVEST_TAXES 0x01
|
||||
int rule_blessed_harvest(void);
|
||||
#define GIVE_SELF 1
|
||||
|
|
|
@ -602,7 +602,7 @@ int rpeasants(const region * r)
|
|||
return value;
|
||||
}
|
||||
|
||||
void rsetpeasants(region * r, int value)
|
||||
int rsetpeasants(region * r, int value)
|
||||
{
|
||||
assert(r->land || value==0);
|
||||
assert(value >= 0);
|
||||
|
@ -612,7 +612,9 @@ void rsetpeasants(region * r, int value)
|
|||
value = USHRT_MAX;
|
||||
}
|
||||
r->land->peasants = (unsigned short)value;
|
||||
return r->land->peasants;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rmoney(const region * r)
|
||||
|
@ -746,17 +748,16 @@ int rsettrees(const region * r, int ageclass, int value)
|
|||
{
|
||||
if (!r->land) {
|
||||
assert(value == 0);
|
||||
return 0;
|
||||
}
|
||||
assert(value >= 0);
|
||||
if (value < MAXTREES) {
|
||||
r->land->trees[ageclass] = value;
|
||||
}
|
||||
else {
|
||||
assert(value >= 0);
|
||||
if (value <= MAXTREES) {
|
||||
return r->land->trees[ageclass] = value;
|
||||
}
|
||||
else {
|
||||
r->land->trees[ageclass] = MAXTREES;
|
||||
}
|
||||
r->land->trees[ageclass] = MAXTREES;
|
||||
}
|
||||
return 0;
|
||||
return r->land->trees[ageclass];
|
||||
}
|
||||
|
||||
region *region_create(int uid)
|
||||
|
@ -1095,11 +1096,10 @@ void init_region(region *r)
|
|||
|
||||
if (!fval(r, RF_CHAOTIC)) {
|
||||
int peasants;
|
||||
int p_wage = 1 + peasant_wage(r, false) + rng_int() % 5;
|
||||
peasants = (region_maxworkers(r) * (20 + dice(6, 10))) / 100;
|
||||
if (peasants < 100) peasants = 100;
|
||||
rsetpeasants(r, peasants);
|
||||
rsetmoney(r, rpeasants(r) * ((wage(r, NULL, NULL,
|
||||
INT_MAX) + 1) + rng_int() % 5));
|
||||
rsetmoney(r, rsetpeasants(r, peasants) * p_wage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@ extern "C" {
|
|||
int rsettrees(const struct region *r, int ageclass, int value);
|
||||
|
||||
int rpeasants(const struct region *r);
|
||||
void rsetpeasants(struct region *r, int value);
|
||||
int rsetpeasants(struct region *r, int value);
|
||||
int rmoney(const struct region *r);
|
||||
void rsetmoney(struct region *r, int value);
|
||||
int rhorses(const struct region *r);
|
||||
|
|
|
@ -743,7 +743,8 @@ void immigration(void)
|
|||
/* if less than 50 are in the region and there is space and no monster or demon units in the region */
|
||||
if (repopulate) {
|
||||
int peasants = rpeasants(r);
|
||||
int income = wage(r, NULL, NULL, turn) - maintenance_cost(NULL) + 1;
|
||||
bool mourn = is_mourning(r, turn);
|
||||
int income = peasant_wage(r, mourn) - maintenance_cost(NULL) + 1;
|
||||
if (income >= 0 && r->land && (peasants < repopulate) && region_maxworkers(r) >(peasants + 30) * 2) {
|
||||
int badunit = 0;
|
||||
unit *u;
|
||||
|
@ -754,7 +755,7 @@ void immigration(void)
|
|||
}
|
||||
}
|
||||
if (badunit == 0) {
|
||||
peasants += (int)(rng_double()*income);
|
||||
peasants += (int)(rng_double() * income);
|
||||
rsetpeasants(r, peasants);
|
||||
}
|
||||
}
|
||||
|
@ -836,8 +837,10 @@ void demographics(void)
|
|||
|
||||
if (r->age > 20) {
|
||||
double mwp = fmax(region_maxworkers(r), 1);
|
||||
bool mourn = is_mourning(r, turn);
|
||||
int p_wage = peasant_wage(r, mourn);
|
||||
double prob =
|
||||
pow(rpeasants(r) / (mwp * wage(r, NULL, NULL, turn) * 0.13), 4.0)
|
||||
pow(rpeasants(r) / (mwp * p_wage * 0.13), 4.0)
|
||||
* PLAGUE_CHANCE;
|
||||
|
||||
if (rng_double() < prob) {
|
||||
|
|
|
@ -1182,11 +1182,13 @@ static void report_statistics(struct stream *out, const region * r, const factio
|
|||
if (max_production(r) && (!fval(r->terrain, SEA_REGION)
|
||||
|| f->race == get_race(RC_AQUARIAN))) {
|
||||
if (markets_module()) { /* hack */
|
||||
bool mourn = is_mourning(r, turn);
|
||||
int p_wage = peasant_wage(r, mourn);
|
||||
m =
|
||||
msg_message("nr_stat_salary_new", "max", wage(r, NULL, NULL, turn + 1));
|
||||
msg_message("nr_stat_salary_new", "max", p_wage);
|
||||
}
|
||||
else {
|
||||
m = msg_message("nr_stat_salary", "max", wage(r, f, f->race, turn + 1));
|
||||
m = msg_message("nr_stat_salary", "max", wage(r, f->race));
|
||||
}
|
||||
nr_render(m, f->locale, buf, sizeof(buf), f);
|
||||
paragraph(out, buf, 2, 2, 0);
|
||||
|
@ -1337,7 +1339,7 @@ report_template(const char *filename, report_context * ctx, const char *bom)
|
|||
}
|
||||
rps_nowrap(out, buf);
|
||||
newline(out);
|
||||
sprintf(buf, "; ECheck Lohn %d", wage(r, f, f->race, turn + 1));
|
||||
sprintf(buf, "; ECheck Lohn %d", wage(r, f->race));
|
||||
rps_nowrap(out, buf);
|
||||
newline(out);
|
||||
newline(out);
|
||||
|
|
Loading…
Reference in New Issue