forked from github/server
Refactor: extract can_recruit, write tests for insects.
This commit is contained in:
parent
3880960acf
commit
8d88579570
6 changed files with 128 additions and 89 deletions
152
src/economy.c
152
src/economy.c
|
@ -426,6 +426,59 @@ static int recruit_cost(const faction * f, const race * rc)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message *can_recruit(unit *u, const race *rc, order *ord, int now)
|
||||||
|
{
|
||||||
|
region *r = u->region;
|
||||||
|
|
||||||
|
/* this is a very special case because the recruiting unit may be empty
|
||||||
|
* at this point and we have to look at the creating unit instead. This
|
||||||
|
* is done in cansee, which is called indirectly by is_guarded(). */
|
||||||
|
if (is_guarded(r, u)) {
|
||||||
|
return msg_error(u, ord, 70);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == get_race(RC_INSECT)) {
|
||||||
|
gamedate date;
|
||||||
|
get_gamedate(now, &date);
|
||||||
|
if (date.season == SEASON_WINTER && r->terrain != newterrain(T_DESERT)) {
|
||||||
|
bool usepotion = false;
|
||||||
|
unit *u2;
|
||||||
|
|
||||||
|
for (u2 = r->units; u2; u2 = u2->next) {
|
||||||
|
if (fval(u2, UFL_WARMTH)) {
|
||||||
|
usepotion = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!usepotion) {
|
||||||
|
return msg_error(u, ord, 98);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* in Gletschern, Eisbergen gar nicht rekrutieren */
|
||||||
|
if (r_insectstalled(r)) {
|
||||||
|
return msg_error(u, ord, 97);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_cursed(r->attribs, &ct_riotzone)) {
|
||||||
|
/* Die Region befindet sich in Aufruhr */
|
||||||
|
return msg_error(u, ord, 237);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc && !playerrace(rc)) {
|
||||||
|
return msg_error(u, ord, 139);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fval(u, UFL_HERO)) {
|
||||||
|
return msg_feedback(u, ord, "error_herorecruit", "");
|
||||||
|
}
|
||||||
|
if (has_skill(u, SK_MAGIC)) {
|
||||||
|
/* error158;de;{unit} in {region}: '{command}' - Magier arbeiten
|
||||||
|
* grunds<EFBFBD>tzlich nur alleine! */
|
||||||
|
return msg_error(u, ord, 158);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void recruit(unit * u, struct order *ord, econ_request ** recruitorders)
|
static void recruit(unit * u, struct order *ord, econ_request ** recruitorders)
|
||||||
{
|
{
|
||||||
region *r = u->region;
|
region *r = u->region;
|
||||||
|
@ -434,6 +487,7 @@ static void recruit(unit * u, struct order *ord, econ_request ** recruitorders)
|
||||||
const faction *f = u->faction;
|
const faction *f = u->faction;
|
||||||
const struct race *rc = u_race(u);
|
const struct race *rc = u_race(u);
|
||||||
int n;
|
int n;
|
||||||
|
message *msg;
|
||||||
|
|
||||||
init_order_depr(ord);
|
init_order_depr(ord);
|
||||||
n = getint();
|
n = getint();
|
||||||
|
@ -456,6 +510,7 @@ static void recruit(unit * u, struct order *ord, econ_request ** recruitorders)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recruitcost < 0) {
|
if (recruitcost < 0) {
|
||||||
rc = u_race(u);
|
rc = u_race(u);
|
||||||
recruitcost = recruit_cost(f, rc);
|
recruitcost = recruit_cost(f, rc);
|
||||||
|
@ -463,95 +518,46 @@ static void recruit(unit * u, struct order *ord, econ_request ** recruitorders)
|
||||||
recruitcost = INT_MAX;
|
recruitcost = INT_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(rc);
|
|
||||||
u_setrace(u, rc);
|
|
||||||
|
|
||||||
/* this is a very special case because the recruiting unit may be empty
|
if (recruitcost > 0) {
|
||||||
* at this point and we have to look at the creating unit instead. This
|
int pool;
|
||||||
* is done in cansee, which is called indirectly by is_guarded(). */
|
|
||||||
if (is_guarded(r, u)) {
|
|
||||||
cmistake(u, ord, 70, MSG_EVENT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == get_race(RC_INSECT)) {
|
|
||||||
gamedate date;
|
|
||||||
get_gamedate(turn, &date);
|
|
||||||
if (date.season == SEASON_WINTER && r->terrain != newterrain(T_DESERT)) {
|
|
||||||
bool usepotion = false;
|
|
||||||
unit *u2;
|
|
||||||
|
|
||||||
for (u2 = r->units; u2; u2 = u2->next)
|
|
||||||
if (fval(u2, UFL_WARMTH)) {
|
|
||||||
usepotion = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!usepotion)
|
|
||||||
{
|
|
||||||
cmistake(u, ord, 98, MSG_EVENT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* in Gletschern, Eisbergen gar nicht rekrutieren */
|
|
||||||
if (r_insectstalled(r)) {
|
|
||||||
cmistake(u, ord, 97, MSG_EVENT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (is_cursed(r->attribs, &ct_riotzone)) {
|
|
||||||
/* Die Region befindet sich in Aufruhr */
|
|
||||||
cmistake(u, ord, 237, MSG_EVENT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (recruitcost) {
|
|
||||||
plane *pl = getplane(r);
|
plane *pl = getplane(r);
|
||||||
if (pl && fval(pl, PFL_NORECRUITS)) {
|
|
||||||
|
if (pl && (pl->flags & PFL_NORECRUITS)) {
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_pflnorecruit", ""));
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_pflnorecruit", ""));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT,
|
pool = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, recruitcost * n);
|
||||||
recruitcost) < recruitcost) {
|
if (pool < recruitcost) {
|
||||||
cmistake(u, ord, 142, MSG_EVENT);
|
cmistake(u, ord, 142, MSG_EVENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
pool /= recruitcost;
|
||||||
|
if (n > pool) n = pool;
|
||||||
}
|
}
|
||||||
if (!playerrace(rc)) {
|
|
||||||
cmistake(u, ord, 139, MSG_EVENT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fval(u, UFL_HERO)) {
|
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_herorecruit", ""));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (has_skill(u, SK_MAGIC)) {
|
|
||||||
/* error158;de;{unit} in {region}: '{command}' - Magier arbeiten
|
|
||||||
* grunds<EFBFBD>tzlich nur alleine! */
|
|
||||||
cmistake(u, ord, 158, MSG_EVENT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (has_skill(u, SK_ALCHEMY)
|
|
||||||
&& count_skill(u->faction, SK_ALCHEMY) + n >
|
|
||||||
skill_limit(u->faction, SK_ALCHEMY)) {
|
|
||||||
cmistake(u, ord, 156, MSG_EVENT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (recruitcost > 0) {
|
|
||||||
int pooled =
|
|
||||||
get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, recruitcost * n);
|
|
||||||
int pr = pooled / recruitcost;
|
|
||||||
if (n > pr) n = pr;
|
|
||||||
}
|
|
||||||
|
|
||||||
u->wants = n;
|
|
||||||
|
|
||||||
if (!n) {
|
if (!n) {
|
||||||
cmistake(u, ord, 142, MSG_EVENT);
|
cmistake(u, ord, 142, MSG_EVENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (has_skill(u, SK_ALCHEMY)) {
|
||||||
|
if (count_skill(u->faction, SK_ALCHEMY) + n > skill_limit(u->faction, SK_ALCHEMY)) {
|
||||||
|
cmistake(u, ord, 156, MSG_EVENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(rc);
|
||||||
|
msg = can_recruit(u, rc, ord, turn);
|
||||||
|
if (msg) {
|
||||||
|
add_message(&u->faction->msgs, msg);
|
||||||
|
msg_release(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_setrace(u, rc);
|
||||||
|
u->wants = n;
|
||||||
o = (econ_request *)calloc(1, sizeof(econ_request));
|
o = (econ_request *)calloc(1, sizeof(econ_request));
|
||||||
o->qty = n;
|
o->qty = n;
|
||||||
o->unit = u;
|
o->unit = u;
|
||||||
|
|
|
@ -44,6 +44,7 @@ extern "C" {
|
||||||
#define MAXNEWBIES 5
|
#define MAXNEWBIES 5
|
||||||
|
|
||||||
struct unit;
|
struct unit;
|
||||||
|
struct race;
|
||||||
struct region;
|
struct region;
|
||||||
struct faction;
|
struct faction;
|
||||||
struct order;
|
struct order;
|
||||||
|
@ -94,6 +95,7 @@ extern "C" {
|
||||||
void steal_cmd(struct unit * u, struct order *ord, struct econ_request ** stealorders);
|
void steal_cmd(struct unit * u, struct order *ord, struct econ_request ** stealorders);
|
||||||
void expandstealing(struct region * r, struct econ_request * stealorders);
|
void expandstealing(struct region * r, struct econ_request * stealorders);
|
||||||
|
|
||||||
|
struct message *can_recruit(struct unit *u, const struct race *rc, struct order *ord, int now);
|
||||||
void add_recruits(struct unit * u, int number, int wanted);
|
void add_recruits(struct unit * u, int number, int wanted);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -480,6 +480,35 @@ static void test_recruit(CuTest *tc) {
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_recruit_insect(CuTest *tc) {
|
||||||
|
unit *u;
|
||||||
|
faction *f;
|
||||||
|
message * msg;
|
||||||
|
|
||||||
|
test_setup();
|
||||||
|
test_create_calendar();
|
||||||
|
f = test_create_faction(test_create_race("insect"));
|
||||||
|
u = test_create_unit(f, test_create_region(0, 0, NULL));
|
||||||
|
u->thisorder = create_order(K_RECRUIT, f->locale, "%d", 1);
|
||||||
|
|
||||||
|
msg = can_recruit(u, f->race, u->thisorder, 1083); /* Autumn */
|
||||||
|
CuAssertPtrEquals(tc, NULL, msg);
|
||||||
|
|
||||||
|
msg = can_recruit(u, f->race, u->thisorder, 1084); /* Insects, Winter */
|
||||||
|
CuAssertPtrNotNull(tc, msg);
|
||||||
|
msg_release(msg);
|
||||||
|
|
||||||
|
u->flags |= UFL_WARMTH;
|
||||||
|
msg = can_recruit(u, f->race, u->thisorder, 1084); /* Insects, potion, Winter */
|
||||||
|
CuAssertPtrEquals(tc, NULL, msg);
|
||||||
|
|
||||||
|
u->flags = 0;
|
||||||
|
msg = can_recruit(u, NULL, u->thisorder, 1084); /* Other races, Winter */
|
||||||
|
CuAssertPtrEquals(tc, NULL, msg);
|
||||||
|
|
||||||
|
test_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
static void test_income(CuTest *tc)
|
static void test_income(CuTest *tc)
|
||||||
{
|
{
|
||||||
race *rc;
|
race *rc;
|
||||||
|
@ -764,6 +793,7 @@ CuSuite *get_economy_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_trade_insect);
|
SUITE_ADD_TEST(suite, test_trade_insect);
|
||||||
SUITE_ADD_TEST(suite, test_maintain_buildings);
|
SUITE_ADD_TEST(suite, test_maintain_buildings);
|
||||||
SUITE_ADD_TEST(suite, test_recruit);
|
SUITE_ADD_TEST(suite, test_recruit);
|
||||||
|
SUITE_ADD_TEST(suite, test_recruit_insect);
|
||||||
SUITE_ADD_TEST(suite, test_loot);
|
SUITE_ADD_TEST(suite, test_loot);
|
||||||
SUITE_ADD_TEST(suite, test_expand_production);
|
SUITE_ADD_TEST(suite, test_expand_production);
|
||||||
return suite;
|
return suite;
|
||||||
|
|
|
@ -785,27 +785,12 @@ static void test_stealth_modifier(CuTest *tc) {
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_calendar(void) {
|
|
||||||
months_per_year = 9;
|
|
||||||
month_season = malloc(sizeof(int) * months_per_year);
|
|
||||||
month_season[0] = SEASON_SUMMER;
|
|
||||||
month_season[1] = SEASON_AUTUMN;
|
|
||||||
month_season[2] = SEASON_AUTUMN;
|
|
||||||
month_season[3] = SEASON_WINTER;
|
|
||||||
month_season[4] = SEASON_WINTER;
|
|
||||||
month_season[5] = SEASON_WINTER;
|
|
||||||
month_season[6] = SEASON_SPRING;
|
|
||||||
month_season[7] = SEASON_SPRING;
|
|
||||||
month_season[8] = SEASON_SUMMER;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_insect_warnings(CuTest *tc) {
|
static void test_insect_warnings(CuTest *tc) {
|
||||||
faction *f;
|
faction *f;
|
||||||
gamedate gd;
|
gamedate gd;
|
||||||
|
|
||||||
test_setup();
|
test_setup();
|
||||||
setup_calendar();
|
test_create_calendar();
|
||||||
config_set_int("game.start", 184);
|
|
||||||
test_inject_messagetypes();
|
test_inject_messagetypes();
|
||||||
f = test_create_faction(test_create_race("insect"));
|
f = test_create_faction(test_create_race("insect"));
|
||||||
|
|
||||||
|
|
15
src/tests.c
15
src/tests.c
|
@ -260,6 +260,21 @@ static void test_reset(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_create_calendar(void) {
|
||||||
|
config_set_int("game.start", 184);
|
||||||
|
months_per_year = 9;
|
||||||
|
month_season = malloc(sizeof(int) * months_per_year);
|
||||||
|
month_season[0] = SEASON_SUMMER;
|
||||||
|
month_season[1] = SEASON_AUTUMN;
|
||||||
|
month_season[2] = SEASON_AUTUMN;
|
||||||
|
month_season[3] = SEASON_WINTER;
|
||||||
|
month_season[4] = SEASON_WINTER;
|
||||||
|
month_season[5] = SEASON_WINTER;
|
||||||
|
month_season[6] = SEASON_SPRING;
|
||||||
|
month_season[7] = SEASON_SPRING;
|
||||||
|
month_season[8] = SEASON_SUMMER;
|
||||||
|
}
|
||||||
|
|
||||||
void test_inject_messagetypes(void)
|
void test_inject_messagetypes(void)
|
||||||
{
|
{
|
||||||
message_handle_missing(MESSAGE_MISSING_REPLACE);
|
message_handle_missing(MESSAGE_MISSING_REPLACE);
|
||||||
|
|
|
@ -40,6 +40,7 @@ extern "C" {
|
||||||
struct log_t * test_log_start(int flags, struct strlist **slist);
|
struct log_t * test_log_start(int flags, struct strlist **slist);
|
||||||
void test_log_stop(struct log_t *log, struct strlist *slist);
|
void test_log_stop(struct log_t *log, struct strlist *slist);
|
||||||
|
|
||||||
|
void test_create_calendar(void);
|
||||||
struct locale * test_create_locale(void);
|
struct locale * test_create_locale(void);
|
||||||
struct terrain_type * test_create_terrain(const char * name, int flags);
|
struct terrain_type * test_create_terrain(const char * name, int flags);
|
||||||
struct race *test_create_race(const char *name);
|
struct race *test_create_race(const char *name);
|
||||||
|
|
Loading…
Reference in a new issue