forked from github/server
tests for plan_monster
This commit is contained in:
parent
384a2ea7d7
commit
a366cd4b17
5 changed files with 259 additions and 5 deletions
|
@ -200,6 +200,7 @@ set(TESTS_SRC
|
||||||
laws.test.c
|
laws.test.c
|
||||||
magic.test.c
|
magic.test.c
|
||||||
market.test.c
|
market.test.c
|
||||||
|
monsters.test.c
|
||||||
move.test.c
|
move.test.c
|
||||||
piracy.test.c
|
piracy.test.c
|
||||||
prefix.test.c
|
prefix.test.c
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#define MOVECHANCE 25 /* chance fuer bewegung */
|
#define MOVECHANCE .25 /* chance fuer bewegung */
|
||||||
#define DRAGON_RANGE 20 /* Max. Distanz zum nächsten Drachenziel */
|
#define DRAGON_RANGE 20 /* Max. Distanz zum nächsten Drachenziel */
|
||||||
#define MAXILLUSION_TEXTS 3
|
#define MAXILLUSION_TEXTS 3
|
||||||
|
|
||||||
|
@ -85,6 +85,10 @@ static double monster_attack_chance(void) {
|
||||||
return get_param_flt(global.parameters, "rules.monsters.attack_chance", 0.4f);
|
return get_param_flt(global.parameters, "rules.monsters.attack_chance", 0.4f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double random_move_chance(void) {
|
||||||
|
return get_param_flt(global.parameters, "rules.monsters.random_move_chance", MOVECHANCE);
|
||||||
|
}
|
||||||
|
|
||||||
static void reduce_weight(unit * u)
|
static void reduce_weight(unit * u)
|
||||||
{
|
{
|
||||||
int capacity, weight = 0;
|
int capacity, weight = 0;
|
||||||
|
@ -157,7 +161,7 @@ static order *monster_attack(unit * u, const unit * target)
|
||||||
return create_order(K_ATTACK, u->faction->locale, "%i", target->no);
|
return create_order(K_ATTACK, u->faction->locale, "%i", target->no);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int monster_attacks(unit * monster, bool respect_buildings, bool rich_only)
|
int monster_attacks(unit * monster, bool respect_buildings, bool rich_only)
|
||||||
{
|
{
|
||||||
region *r = monster->region;
|
region *r = monster->region;
|
||||||
unit *u2;
|
unit *u2;
|
||||||
|
@ -786,6 +790,7 @@ void plan_monsters(faction * f)
|
||||||
if (attacking && is_guard(u, GUARD_TAX)) {
|
if (attacking && is_guard(u, GUARD_TAX)) {
|
||||||
monster_attacks(u, true, false);
|
monster_attacks(u, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* units with a plan to kill get ATTACK orders: */
|
/* units with a plan to kill get ATTACK orders: */
|
||||||
ta = a_find(u->attribs, &at_hate);
|
ta = a_find(u->attribs, &at_hate);
|
||||||
if (ta && !monster_is_waiting(u)) {
|
if (ta && !monster_is_waiting(u)) {
|
||||||
|
@ -818,7 +823,7 @@ void plan_monsters(faction * f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (u_race(u)->flags & RCF_MOVERANDOM) {
|
else if (u_race(u)->flags & RCF_MOVERANDOM) {
|
||||||
if (rng_int() % 100 < MOVECHANCE || check_overpopulated(u)) {
|
if (chance(random_move_chance()) || check_overpopulated(u)) {
|
||||||
long_order = monster_move(r, u);
|
long_order = monster_move(r, u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
247
src/monsters.test.c
Normal file
247
src/monsters.test.c
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
#include <platform.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <kernel/config.h>
|
||||||
|
#include <kernel/faction.h>
|
||||||
|
#include <kernel/item.h>
|
||||||
|
#include <kernel/order.h>
|
||||||
|
#include <kernel/race.h>
|
||||||
|
#include <kernel/region.h>
|
||||||
|
#include <kernel/terrain.h>
|
||||||
|
#include <kernel/unit.h>
|
||||||
|
|
||||||
|
#include "monster.h"
|
||||||
|
#include "guard.h"
|
||||||
|
#include "skill.h"
|
||||||
|
|
||||||
|
#include <util/language.h>
|
||||||
|
#include <util/language_struct.h>
|
||||||
|
|
||||||
|
#include <CuTest.h>
|
||||||
|
#include <tests.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
extern void plan_monsters(struct faction *f);
|
||||||
|
extern int monster_attacks(unit * monster, bool respect_buildings, bool rich_only);
|
||||||
|
|
||||||
|
static void init_language(void)
|
||||||
|
{
|
||||||
|
locale* lang;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
lang = get_or_create_locale("de");
|
||||||
|
locale_setstring(lang, "skill::unarmed", "Waffenloser Kampf");
|
||||||
|
locale_setstring(lang, "keyword::attack", "ATTACKIERE");
|
||||||
|
locale_setstring(lang, "keyword::study", "LERNE");
|
||||||
|
locale_setstring(lang, "keyword::tax", "TREIBE");
|
||||||
|
locale_setstring(lang, "keyword::loot", "PLUENDERE");
|
||||||
|
locale_setstring(lang, "keyword::guard", "BEWACHE");
|
||||||
|
locale_setstring(lang, "keyword::move", "NACH");
|
||||||
|
locale_setstring(lang, "keyword::message", "BOTSCHAFT");
|
||||||
|
locale_setstring(lang, "REGION", "REGION");
|
||||||
|
locale_setstring(lang, "east", "O");
|
||||||
|
|
||||||
|
for (i = 0; i < MAXKEYWORDS; ++i) {
|
||||||
|
if (!locale_getstring(lang, mkname("keyword", keywords[i])))
|
||||||
|
locale_setstring(lang, mkname("keyword", keywords[i]), keywords[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAXSKILLS; ++i) {
|
||||||
|
if (!locale_getstring(lang, mkname("skill", skillnames[i])))
|
||||||
|
locale_setstring(lang, mkname("skill", skillnames[i]), skillnames[i]);
|
||||||
|
}
|
||||||
|
init_keywords(lang);
|
||||||
|
init_skills(lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
static order *find_order(const char *expected, const unit *unit)
|
||||||
|
{
|
||||||
|
char cmd[32];
|
||||||
|
order *order;
|
||||||
|
for (order = unit->orders; order; order = order->next) {
|
||||||
|
if (strcmp(expected, get_command(order, cmd, sizeof(cmd))) == 0) {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void create_monsters(faction **player, faction **monsters, region **r, unit **u, unit **m) {
|
||||||
|
race* rc;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
|
||||||
|
init_language();
|
||||||
|
|
||||||
|
test_create_world();
|
||||||
|
*player = test_create_faction(NULL);
|
||||||
|
*monsters = get_or_create_monsters();
|
||||||
|
assert(rc_find((*monsters)->race->_name));
|
||||||
|
rc = rc_get_or_create((*monsters)->race->_name);
|
||||||
|
fset(rc, RCF_UNARMEDGUARD);
|
||||||
|
fset(rc, RCF_NPC);
|
||||||
|
fset(*monsters, FFL_NOIDLEOUT);
|
||||||
|
assert(fval(*monsters, FFL_NPC) && fval((*monsters)->race, RCF_UNARMEDGUARD) && fval((*monsters)->race, RCF_NPC) && fval(*monsters, FFL_NOIDLEOUT));
|
||||||
|
(*monsters)->locale = default_locale;
|
||||||
|
|
||||||
|
*r = findregion(0, 0);
|
||||||
|
|
||||||
|
*u = test_create_unit(*player, *r);
|
||||||
|
unit_setid(*u, 1);
|
||||||
|
*m = test_create_unit(*monsters, *r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_monsters_attack(CuTest * tc)
|
||||||
|
{
|
||||||
|
faction *f, *f2;
|
||||||
|
region *r;
|
||||||
|
unit *u, *m;
|
||||||
|
|
||||||
|
create_monsters(&f, &f2, &r, &u, &m);
|
||||||
|
|
||||||
|
guard(m, GUARD_TAX);
|
||||||
|
|
||||||
|
set_param(&global.parameters, "rules.monsters.attack_chance", "1");
|
||||||
|
|
||||||
|
plan_monsters(f2);
|
||||||
|
|
||||||
|
CuAssertPtrNotNull(tc, find_order("ATTACKIERE 1", m));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_monsters_attack_ocean(CuTest * tc)
|
||||||
|
{
|
||||||
|
faction *f, *f2;
|
||||||
|
region *r;
|
||||||
|
unit *u, *m;
|
||||||
|
|
||||||
|
create_monsters(&f, &f2, &r, &u, &m);
|
||||||
|
r = findregion(-1, 0);
|
||||||
|
u = test_create_unit(u->faction, r);
|
||||||
|
unit_setid(u, 2);
|
||||||
|
m = test_create_unit(m->faction, r);
|
||||||
|
assert(!m->region->land);
|
||||||
|
|
||||||
|
set_param(&global.parameters, "rules.monsters.attack_chance", "1");
|
||||||
|
|
||||||
|
plan_monsters(f2);
|
||||||
|
|
||||||
|
CuAssertPtrNotNull(tc, find_order("ATTACKIERE 2", m));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_monsters_waiting(CuTest * tc)
|
||||||
|
{
|
||||||
|
faction *f, *f2;
|
||||||
|
region *r;
|
||||||
|
unit *u, *m;
|
||||||
|
|
||||||
|
create_monsters(&f, &f2, &r, &u, &m);
|
||||||
|
guard(m, GUARD_TAX);
|
||||||
|
fset(m, UFL_ISNEW);
|
||||||
|
monster_attacks(m, false, false);
|
||||||
|
CuAssertPtrEquals(tc, 0, find_order("ATTACKIERE 1", m));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_monsters_attack_not(CuTest * tc)
|
||||||
|
{
|
||||||
|
faction *f, *f2;
|
||||||
|
region *r;
|
||||||
|
unit *u, *m;
|
||||||
|
|
||||||
|
create_monsters(&f, &f2, &r, &u, &m);
|
||||||
|
|
||||||
|
guard(m, GUARD_TAX);
|
||||||
|
guard(u, GUARD_TAX);
|
||||||
|
|
||||||
|
set_param(&global.parameters, "rules.monsters.attack_chance", "0");
|
||||||
|
|
||||||
|
plan_monsters(f2);
|
||||||
|
|
||||||
|
CuAssertPtrEquals(tc, 0, find_order("ATTACKIERE 1", m));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_dragon_attacks_the_rich(CuTest * tc)
|
||||||
|
{
|
||||||
|
faction *f, *f2;
|
||||||
|
region *r;
|
||||||
|
unit *u, *m;
|
||||||
|
const item_type *i_silver;
|
||||||
|
|
||||||
|
init_language();
|
||||||
|
create_monsters(&f, &f2, &r, &u, &m);
|
||||||
|
|
||||||
|
guard(m, GUARD_TAX);
|
||||||
|
set_level(m, SK_WEAPONLESS, 10);
|
||||||
|
|
||||||
|
rsetmoney(r, 1);
|
||||||
|
rsetmoney(findregion(1, 0), 0);
|
||||||
|
i_silver = it_find("money");
|
||||||
|
assert(i_silver);
|
||||||
|
i_change(&u->items, i_silver, 5000);
|
||||||
|
|
||||||
|
set_param(&global.parameters, "rules.monsters.attack_chance", "0.00001");
|
||||||
|
|
||||||
|
plan_monsters(f2);
|
||||||
|
|
||||||
|
CuAssertPtrNotNull(tc, find_order("ATTACKIERE 1", m));
|
||||||
|
CuAssertPtrNotNull(tc, find_order("PLUENDERE", m));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_dragon_moves(CuTest * tc)
|
||||||
|
{
|
||||||
|
faction *f, *f2;
|
||||||
|
region *r;
|
||||||
|
unit *u, *m;
|
||||||
|
|
||||||
|
create_monsters(&f, &f2, &r, &u, &m);
|
||||||
|
rsetpeasants(r, 0);
|
||||||
|
rsetmoney(r, 0);
|
||||||
|
rsetmoney(findregion(1, 0), 1000);
|
||||||
|
|
||||||
|
set_level(m, SK_WEAPONLESS, 10);
|
||||||
|
set_param(&global.parameters, "rules.monsters.attack_chance", ".0");
|
||||||
|
plan_monsters(f2);
|
||||||
|
|
||||||
|
CuAssertPtrNotNull(tc, find_order("NACH O", m));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_monsters_learn_exp(CuTest * tc)
|
||||||
|
{
|
||||||
|
faction *f, *f2;
|
||||||
|
region *r;
|
||||||
|
unit *u, *m;
|
||||||
|
skill* sk;
|
||||||
|
|
||||||
|
create_monsters(&f, &f2, &r, &u, &m);
|
||||||
|
set_param(&global.parameters, "study.from_use", "1");
|
||||||
|
|
||||||
|
u_setrace(u, u_race(m));
|
||||||
|
produceexp(u, SK_MELEE, u->number);
|
||||||
|
sk = unit_skill(u, SK_MELEE);
|
||||||
|
CuAssertTrue(tc, !sk);
|
||||||
|
|
||||||
|
produceexp(m, SK_MELEE, u->number);
|
||||||
|
sk = unit_skill(m, SK_MELEE);
|
||||||
|
CuAssertTrue(tc, sk && (sk->level > 0 || (sk->level == 0 && sk->weeks > 0)));
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
CuSuite *get_monsters_suite(void)
|
||||||
|
{
|
||||||
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, test_monsters_attack);
|
||||||
|
SUITE_ADD_TEST(suite, test_monsters_attack_ocean);
|
||||||
|
SUITE_ADD_TEST(suite, test_monsters_waiting);
|
||||||
|
SUITE_ADD_TEST(suite, test_monsters_attack_not);
|
||||||
|
SUITE_ADD_TEST(suite, test_dragon_attacks_the_rich);
|
||||||
|
SUITE_ADD_TEST(suite, test_dragon_moves);
|
||||||
|
SUITE_ADD_TEST(suite, test_monsters_learn_exp);
|
||||||
|
return suite;
|
||||||
|
}
|
|
@ -118,6 +118,7 @@ int RunAllTests(int argc, char *argv[])
|
||||||
ADD_SUITE(give);
|
ADD_SUITE(give);
|
||||||
ADD_SUITE(laws);
|
ADD_SUITE(laws);
|
||||||
ADD_SUITE(market);
|
ADD_SUITE(market);
|
||||||
|
ADD_SUITE(monsters);
|
||||||
ADD_SUITE(move);
|
ADD_SUITE(move);
|
||||||
ADD_SUITE(piracy);
|
ADD_SUITE(piracy);
|
||||||
ADD_SUITE(stealth);
|
ADD_SUITE(stealth);
|
||||||
|
|
|
@ -238,10 +238,10 @@ void test_create_world(void)
|
||||||
test_create_itemtype("iron");
|
test_create_itemtype("iron");
|
||||||
test_create_itemtype("stone");
|
test_create_itemtype("stone");
|
||||||
|
|
||||||
t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION);
|
t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION | FLY_INTO);
|
||||||
t_plain->size = 1000;
|
t_plain->size = 1000;
|
||||||
t_plain->max_road = 100;
|
t_plain->max_road = 100;
|
||||||
t_ocean = test_create_terrain("ocean", SEA_REGION | SAIL_INTO | SWIM_INTO);
|
t_ocean = test_create_terrain("ocean", SEA_REGION | SAIL_INTO | SWIM_INTO | FLY_INTO);
|
||||||
t_ocean->size = 0;
|
t_ocean->size = 0;
|
||||||
|
|
||||||
island[0] = test_create_region(0, 0, t_plain);
|
island[0] = test_create_region(0, 0, t_plain);
|
||||||
|
|
Loading…
Reference in a new issue