Merge remote-tracking branch 'eressea/master'

This commit is contained in:
TomBraun 2014-07-07 10:25:22 +02:00
commit c1c0689dc2
26 changed files with 395 additions and 210 deletions

View file

@ -8305,14 +8305,6 @@
<text locale="en">"Meeoooooow..."</text>
</message>
<message name="migrant_conversion" section="events">
<type>
<arg name="unit" type="unit"/>
</type>
<text locale="de">"Die Götter segnen $unit($unit) mit der richtigen Rasse."</text>
<text locale="en">"The gods are blessing $unit($unit) with the correct race."</text>
</message>
<message name="arena_leave_fail" section="events">
<type>
<arg name="unit" type="unit"/>

View file

@ -18,4 +18,5 @@ fi
$ROOT/$BIN_DIR/eressea/test_eressea
cd $ROOT
$ROOT/$BIN_DIR/eressea/eressea -v0 scripts/runtests.lua
grep ERROR eressea.log
cd $OLDWPD

View file

@ -429,7 +429,7 @@ function test_canoe_passes_through_land()
end
function test_give_50_percent_of_money()
local r = region.create(0, 0, "plain")
local r = region.create(0, 0, "plain")
local u1 = unit.create(faction.create("noreply@eressea.de", "human", "de"), r, 1)
local u2 = unit.create(faction.create("noreply@eressea.de", "orc", "de"), r, 1)
u1.faction.age = 10

View file

@ -246,6 +246,7 @@
<F N="../src/spells/buildingcurse.c"/>
<F N="../cJSON/cJSON.c"/>
<F N="../src/kernel/calendar.c"/>
<F N="../src/callback.c"/>
<F N="../src/triggers/changefaction.c"/>
<F N="../src/triggers/changerace.c"/>
<F N="../src/triggers/clonedied.c"/>
@ -403,6 +404,7 @@
<F N="../src/spells/buildingcurse.h"/>
<F N="../cJSON/cJSON.h"/>
<F N="../src/kernel/calendar.h"/>
<F N="../src/callback.h"/>
<F N="../src/triggers/changefaction.h"/>
<F N="../src/triggers/changerace.h"/>
<F N="../src/triggers/clonedied.h"/>

View file

@ -246,6 +246,7 @@
<F N="../src/util/bsdstring.test.c"/>
<F N="../src/kernel/build.test.c"/>
<F N="../src/kernel/building.test.c"/>
<F N="../src/callback.test.c"/>
<F N="../src/kernel/config.test.c"/>
<F N="../src/kernel/curse.test.c"/>
<F N="../src/direction.test.c"/>

View file

@ -62,6 +62,22 @@ static int tolua_region_get_id(lua_State * L)
return 1;
}
static int tolua_region_get_blocked(lua_State * L)
{
region *self = (region *)tolua_tousertype(L, 1, 0);
lua_pushboolean(L, (self->flags&RF_BLOCKED)!=0);
return 1;
}
static int tolua_region_set_blocked(lua_State * L)
{
region *self = (region *)tolua_tousertype(L, 1, 0);
bool flag = !!tolua_toboolean(L, 2, 1);
if (flag) self->flags |= BLD_WORKING;
else self->flags &= ~BLD_WORKING;
return 0;
}
static int tolua_region_get_x(lua_State * L)
{
region *self = (region *) tolua_tousertype(L, 1, 0);
@ -652,6 +668,9 @@ void tolua_region_open(lua_State * L)
tolua_function(L, TOLUA_CAST "destroy", tolua_region_destroy);
tolua_function(L, TOLUA_CAST "__tostring", tolua_region_tostring);
/* flags */
tolua_variable(L, TOLUA_CAST "blocked", tolua_region_get_blocked, tolua_region_set_blocked);
tolua_variable(L, TOLUA_CAST "id", tolua_region_get_id, NULL);
tolua_variable(L, TOLUA_CAST "x", tolua_region_get_x, NULL);
tolua_variable(L, TOLUA_CAST "y", tolua_region_get_y, NULL);

View file

@ -1,3 +1,3 @@
#define VERSION_MAJOR 3
#define VERSION_MINOR 0
#define VERSION_BUILD 677
#define VERSION_BUILD 678

View file

@ -372,13 +372,19 @@ static int do_recruiting(recruitment * recruits, int available)
use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT,
rc->recruitcost * number);
}
add_recruits(u, number, req->qty);
dec = (int)(number * multi);
if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) {
recruited += dec;
if (u->number == 0 && fval(u, UFL_DEAD)) {
/* unit is empty, dead, and cannot recruit */
number = 0;
}
if (number > 0) {
add_recruits(u, number, req->qty);
dec = (int)(number * multi);
if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) {
recruited += dec;
}
get -= dec;
get -= dec;
}
}
}
return recruited;
@ -390,8 +396,7 @@ static void feedback_give_not_allowed(unit * u, order * ord)
""));
}
static bool check_give(unit * u, unit * u2, const item_type * itype,
int mask)
static bool can_give(const unit * u, const unit * u2, const item_type * itype, int mask)
{
if (u2) {
if (u->faction != u2->faction) {
@ -700,6 +705,13 @@ int give_control_cmd(unit * u, order * ord)
return 0;
}
message *check_give(const unit *u, const unit *u2, order * ord) {
if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) {
return msg_feedback(u, ord, "feedback_give_forbidden", "");
}
return 0;
}
static void give_cmd(unit * u, order * ord)
{
region *r = u->region;
@ -709,6 +721,7 @@ static void give_cmd(unit * u, order * ord)
const item_type *itype;
param_t p;
plane *pl;
message *msg;
init_tokens(ord);
skip_token();
@ -729,9 +742,10 @@ static void give_cmd(unit * u, order * ord)
return;
}
if (!check_give(u, u2, NULL, GIVE_ALLITEMS)) {
feedback_give_not_allowed(u, ord);
return;
msg = check_give(u, u2, ord);
if (msg) {
ADDMSG(&u->faction->msgs, msg);
return;
}
/* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */
@ -773,7 +787,7 @@ static void give_cmd(unit * u, order * ord)
msg_feedback(u, ord, "race_nogive", "race", u_race(u)));
return;
}
if (!check_give(u, u2, NULL, GIVE_HERBS)) {
if (!can_give(u, u2, NULL, GIVE_HERBS)) {
feedback_give_not_allowed(u, ord);
return;
}
@ -831,7 +845,7 @@ static void give_cmd(unit * u, order * ord)
else if (p == P_ANY) {
const char *s;
if (!check_give(u, u2, NULL, GIVE_ALLITEMS)) {
if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) {
feedback_give_not_allowed(u, ord);
return;
}
@ -888,7 +902,7 @@ static void give_cmd(unit * u, order * ord)
if (itype != NULL) {
item *i = *i_find(&u->items, itype);
if (i != NULL) {
if (check_give(u, u2, itype, 0)) {
if (can_give(u, u2, itype, 0)) {
n = i->number - get_reservation(u, itype->rtype);
give_item(n, itype, u, u2, ord);
} else {
@ -941,7 +955,7 @@ static void give_cmd(unit * u, order * ord)
itype = finditemtype(s, u->faction->locale);
if (itype != NULL) {
if (check_give(u, u2, itype, 0)) {
if (can_give(u, u2, itype, 0)) {
give_item(n, itype, u, u2, ord);
} else {
feedback_give_not_allowed(u, ord);
@ -2747,6 +2761,24 @@ static int max_skill(region * r, faction * f, skill_t sk)
return w;
}
message * check_steal(const unit * u, struct order *ord) {
plane *pl;
if (fval(u_race(u), RCF_NOSTEAL)) {
return msg_feedback(u, ord, "race_nosteal", "race", u_race(u));
}
if (fval(u->region->terrain, SEA_REGION) && u_race(u) != get_race(RC_AQUARIAN)) {
return msg_feedback(u, ord, "error_onlandonly", "");
}
pl = rplane(u->region);
if (pl && fval(pl, PFL_NOATTACK)) {
return msg_feedback(u, ord, "error270", "");
}
return 0;
}
static void steal_cmd(unit * u, struct order *ord, request ** stealorders)
{
const resource_type *rring = get_resourcetype(R_RING_OF_NIMBLEFINGER);
@ -2756,27 +2788,15 @@ static void steal_cmd(unit * u, struct order *ord, request ** stealorders)
unit *u2 = NULL;
region *r = u->region;
faction *f = NULL;
plane *pl;
message * msg;
assert(skill_enabled(SK_PERCEPTION) && skill_enabled(SK_STEALTH));
if (!fval(u_race(u), RCF_CANSTEAL)) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nosteal", "race",
u_race(u)));
return;
msg = check_steal(u, ord);
if (msg) {
ADDMSG(&u->faction->msgs, msg);
return;
}
if (fval(r->terrain, SEA_REGION) && u_race(u) != get_race(RC_AQUARIAN)) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_onlandonly", ""));
return;
}
pl = rplane(r);
if (pl && fval(pl, PFL_NOATTACK)) {
cmistake(u, ord, 270, MSG_INCOME);
return;
}
init_tokens(ord);
skip_token();
id = read_unitid(u->faction, r);

View file

@ -57,6 +57,9 @@ extern "C" {
extern int give_control_cmd(struct unit *u, struct order *ord);
extern void give_control(struct unit * u, struct unit * u2);
struct message * check_steal(const struct unit * u, struct order *ord);
struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord);
#ifdef __cplusplus
}
#endif

View file

@ -1,61 +1,173 @@
#include <platform.h>
#include <kernel/config.h>
#include <kernel/types.h>
#include "economy.h"
#include <util/message.h>
#include <kernel/unit.h>
#include <kernel/race.h>
#include <kernel/region.h>
#include <kernel/building.h>
#include <kernel/ship.h>
#include <kernel/terrain.h>
#include <CuTest.h>
#include <tests.h>
static void test_give_control_building(CuTest * tc)
{
unit *u1, *u2;
building *b;
struct faction *f;
region *r;
unit *u1, *u2;
building *b;
struct faction *f;
region *r;
test_cleanup();
test_create_world();
f = test_create_faction(0);
r = findregion(0, 0);
b = test_create_building(r, 0);
u1 = test_create_unit(f, r);
u_set_building(u1, b);
u2 = test_create_unit(f, r);
u_set_building(u2, b);
CuAssertPtrEquals(tc, u1, building_owner(b));
give_control(u1, u2);
CuAssertPtrEquals(tc, u2, building_owner(b));
test_cleanup();
test_create_world();
f = test_create_faction(0);
r = findregion(0, 0);
b = test_create_building(r, 0);
u1 = test_create_unit(f, r);
u_set_building(u1, b);
u2 = test_create_unit(f, r);
u_set_building(u2, b);
CuAssertPtrEquals(tc, u1, building_owner(b));
give_control(u1, u2);
CuAssertPtrEquals(tc, u2, building_owner(b));
test_cleanup();
}
static void test_give_control_ship(CuTest * tc)
{
unit *u1, *u2;
ship *sh;
struct faction *f;
region *r;
unit *u1, *u2;
ship *sh;
struct faction *f;
region *r;
test_cleanup();
test_create_world();
f = test_create_faction(0);
r = findregion(0, 0);
sh = test_create_ship(r, 0);
u1 = test_create_unit(f, r);
u_set_ship(u1, sh);
u2 = test_create_unit(f, r);
u_set_ship(u2, sh);
CuAssertPtrEquals(tc, u1, ship_owner(sh));
give_control(u1, u2);
CuAssertPtrEquals(tc, u2, ship_owner(sh));
test_cleanup();
test_create_world();
f = test_create_faction(0);
r = findregion(0, 0);
sh = test_create_ship(r, 0);
u1 = test_create_unit(f, r);
u_set_ship(u1, sh);
u2 = test_create_unit(f, r);
u_set_ship(u2, sh);
CuAssertPtrEquals(tc, u1, ship_owner(sh));
give_control(u1, u2);
CuAssertPtrEquals(tc, u2, ship_owner(sh));
test_cleanup();
}
struct steal {
struct unit *u;
struct region *r;
struct faction *f;
};
static void setup_steal(struct steal *env, terrain_type *ter, race *rc) {
env->r = test_create_region(0, 0, ter);
env->f = test_create_faction(rc);
env->u = test_create_unit(env->f, env->r);
}
static void test_steal_okay(CuTest * tc) {
struct steal env;
race *rc;
terrain_type *ter;
test_cleanup();
ter = test_create_terrain("plain", LAND_REGION);
rc = test_create_race("human");
rc->flags = 0;
setup_steal(&env, ter, rc);
CuAssertPtrEquals(tc, 0, check_steal(env.u, 0));
test_cleanup();
}
static void test_steal_nosteal(CuTest * tc) {
struct steal env;
race *rc;
terrain_type *ter;
message *msg;
test_cleanup();
ter = test_create_terrain("plain", LAND_REGION);
rc = test_create_race("human");
rc->flags = RCF_NOSTEAL;
setup_steal(&env, ter, rc);
CuAssertPtrNotNull(tc, msg = check_steal(env.u, 0));
msg_release(msg);
test_cleanup();
}
static void test_steal_ocean(CuTest * tc) {
struct steal env;
race *rc;
terrain_type *ter;
message *msg;
test_cleanup();
ter = test_create_terrain("ocean", SEA_REGION);
rc = test_create_race("human");
setup_steal(&env, ter, rc);
CuAssertPtrNotNull(tc, msg = check_steal(env.u, 0));
msg_release(msg);
test_cleanup();
}
struct give {
struct unit *src, *dst;
struct region *r;
struct faction *f1, *f2;
};
static void setup_give(struct give *env) {
terrain_type *ter = test_create_terrain("plain", LAND_REGION);
env->r = test_create_region(0, 0, ter);
env->src = test_create_unit(env->f1, env->r);
env->dst = test_create_unit(env->f2, env->r);
}
static void test_give_okay(CuTest * tc) {
struct give env;
struct race * rc;
test_cleanup();
rc = test_create_race("human");
env.f2 = env.f1 = test_create_faction(rc);
setup_give(&env);
set_param(&global.parameters, "rules.give", "0");
CuAssertPtrEquals(tc, 0, check_give(env.src, env.dst, 0));
test_cleanup();
}
static void test_give_denied_by_rules(CuTest * tc) {
struct give env;
struct race * rc;
struct message *msg;
test_cleanup();
rc = test_create_race("human");
env.f1 = test_create_faction(rc);
env.f2 = test_create_faction(rc);
setup_give(&env);
set_param(&global.parameters, "rules.give", "0");
CuAssertPtrNotNull(tc, msg=check_give(env.src, env.dst, 0));
msg_release(msg);
test_cleanup();
}
CuSuite *get_economy_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_give_control_building);
SUITE_ADD_TEST(suite, test_give_control_ship);
return suite;
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_give_control_building);
SUITE_ADD_TEST(suite, test_give_control_ship);
SUITE_ADD_TEST(suite, test_steal_okay);
SUITE_ADD_TEST(suite, test_steal_ocean);
SUITE_ADD_TEST(suite, test_steal_nosteal);
SUITE_ADD_TEST(suite, test_give_okay);
SUITE_ADD_TEST(suite, test_give_denied_by_rules);
return suite;
}

View file

@ -49,11 +49,10 @@ void game_done(void)
void game_init(void)
{
kernel_init();
kernel_init();
register_triggers();
register_xmas();
register_reports();
register_nr();
register_cr();

View file

@ -95,21 +95,19 @@ static bool limited_give(const item_type * type)
int give_quota(const unit * src, const unit * dst, const item_type * type,
int n)
{
static float divisor = -1;
float divisor;
if (divisor == 0 || !limited_give(type)) {
if (!limited_give(type)) {
return n;
}
if (dst && src && src->faction != dst->faction) {
if (divisor < 0) {
divisor = get_param_flt(global.parameters, "rules.items.give_divisor", 1);
assert(divisor == 0 || divisor >= 1);
}
if (divisor >= 1) {
/* predictable > correct: */
int x = (int)(n / divisor);
return x;
}
if (divisor >= 1) {
/* predictable > correct: */
int x = (int)(n / divisor);
return x;
}
}
return n;
}

View file

@ -2661,6 +2661,7 @@ static void aftermath(battle * b)
int dead = dead_fighters(df);
int sum_hp = 0;
int n;
int flags = 0;
for (n = 0; n != df->alive; ++n) {
if (df->person[n].hp > 0) {
@ -2669,11 +2670,16 @@ static void aftermath(battle * b)
}
snumber += du->number;
if (relevant) {
int flags = UFL_LONGACTION | UFL_NOTMOVING;
flags = UFL_LONGACTION | UFL_NOTMOVING;
if (du->status == ST_FLEE) {
flags -= UFL_NOTMOVING;
}
fset(du, flags);
}
if (df->alive == 0) {
flags |= UFL_DEAD;
}
if (flags) {
fset(du, flags);
}
if (sum_hp + df->run.hp < du->hp) {
/* someone on the ship got damaged, damage the ship */
@ -4057,70 +4063,6 @@ static bool start_battle(region * r, battle ** bp)
return fighting;
}
static void battle_stats(FILE * F, battle * b)
{
typedef struct stat_info {
struct stat_info *next;
const weapon_type *wtype;
int level;
int number;
} stat_info;
side *s;
for (s = b->sides; s != b->sides + b->nsides; ++s) {
fighter *df;
stat_info *stats = NULL, *stat;
for (df = s->fighters; df; df = df->next) {
unit *du = df->unit;
troop dt;
stat_info *slast = NULL;
dt.fighter = df;
for (dt.index = 0; dt.index != du->number; ++dt.index) {
weapon *wp = preferred_weapon(dt, true);
int level = wp ? wp->attackskill : 0;
const weapon_type *wtype = wp ? wp->type : NULL;
stat_info **slist = &stats;
if (slast && slast->wtype == wtype && slast->level == level) {
++slast->number;
continue;
}
while (*slist && (*slist)->wtype != wtype) {
slist = &(*slist)->next;
}
while (*slist && (*slist)->wtype == wtype && (*slist)->level > level) {
slist = &(*slist)->next;
}
stat = *slist;
if (stat == NULL || stat->wtype != wtype || stat->level != level) {
stat = (stat_info*)calloc(1, sizeof(stat_info));
stat->wtype = wtype;
stat->level = level;
stat->next = *slist;
*slist = stat;
}
slast = stat;
++slast->number;
}
}
fprintf(F, "##STATS## Heer %u - %s:\n", army_index(s),
factionname(s->faction));
for (stat = stats; stat != NULL; stat = stat->next) {
fprintf(F, "%s %u : %u\n",
stat->wtype ? stat->wtype->itype->rtype->_name[0] : "none", stat->level,
stat->number);
}
while (stats) {
stat_info *stat = stats;
stats = stat->next;
free(stat);
}
}
}
/** execute one round of attacks
* fig->fighting is used to determine who attacks, not fig->alive, since
* the latter may be influenced by attacks that already took place.
@ -4289,9 +4231,6 @@ void do_battle(region * r)
b->has_tactics_turn = false;
}
if (b->region->flags & RF_COMBATDEBUG)
battle_stats(bdebug, b);
/* PRECOMBATSPELLS */
do_combatmagic(b, DO_PRECOMBATSPELL);

View file

@ -46,6 +46,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "plane.h"
#include "pool.h"
#include "race.h"
#include "reports.h"
#include "region.h"
#include "save.h"
#include "ship.h"
@ -2744,8 +2745,13 @@ void attrib_init(void)
void kernel_init(void)
{
attrib_init();
translation_init();
register_reports();
if (!mt_find("missing_message")) {
mt_register(mt_new_va("missing_message", "name:string", 0));
mt_register(mt_new_va("missing_feedback", "unit:unit", "region:region", "command:order", "name:string", 0));
}
attrib_init();
translation_init();
}
static order * defaults[MAXLOCALES];

View file

@ -106,8 +106,9 @@ static void json_maintenance_i(cJSON *json, maintenance *mt) {
mt->flags = json_flags(child, flags);
}
else {
log_error_n("maintenance contains unknown attribute %s", child->string);
log_error_n("maintenance contains unknown array %s", child->string);
}
break;
default:
log_error_n("maintenance contains unknown attribute %s", child->string);
}
@ -325,15 +326,19 @@ static void json_ship(cJSON *json, ship_type *st) {
static void json_race(cJSON *json, race *rc) {
cJSON *child;
const char *flags[] = {
"playerrace", "killpeasants", "scarepeasants",
"cansteal", "moverandom", "cannotmove",
"npc", "killpeasants", "scarepeasants",
"nosteal", "moverandom", "cannotmove",
"learn", "fly", "swim", "walk", "nolearn",
"noteach", "horse", "desert",
"illusionary", "absorbpeasants", "noheal",
"noweapons", "shapeshift", "", "undead", "dragon",
"coastal", "", "cansail", 0
};
if (json->type!=cJSON_Object) {
const char *ecflags[] = {
"", "giveitem", "giveperson",
"giveunit", "getitem", 0
};
if (json->type != cJSON_Object) {
log_error_n("race %s is not a json object: %d", json->string, json->type);
return;
}
@ -380,6 +385,7 @@ static void json_race(cJSON *json, race *rc) {
case cJSON_Array:
if (strcmp(child->string, "flags")==0) {
rc->flags = json_flags(child, flags);
rc->ec_flags = json_flags(child, ecflags);
}
break;
}

View file

@ -16,29 +16,41 @@
#include <tests.h>
#include <stdio.h>
static void check_flag(CuTest *tc, const char *name, int flag) {
static const struct race * race_with_flag(const char * name) {
char data[1024];
const struct race *rc;
cJSON *json;
sprintf(data, "{\"races\" : { \"orc\": { \"speed\" : 1, \"flags\" : [ \"%s\"] }}}", name);
json = cJSON_Parse(data);
free_races();
json_config(json);
rc = rc_find("orc");
return rc_find("orc");
}
static void check_ec_flag(CuTest *tc, const char *name, int flag) {
const struct race *rc = race_with_flag(name);
CuAssertPtrNotNull(tc, rc);
CuAssertIntEquals(tc, flag, rc->ec_flags);
}
static void check_flag(CuTest *tc, const char *name, int flag) {
const struct race *rc = race_with_flag(name);
CuAssertPtrNotNull(tc, rc);
CuAssertIntEquals(tc, flag, rc->flags);
CuAssertDblEquals(tc, 1.0f, rc->speed, 0.0f);
}
static void test_flags(CuTest *tc) {
check_flag(tc, "playerrace", RCF_PLAYERRACE);
check_flag(tc, "npc", RCF_NPC);
check_flag(tc, "scarepeasants", RCF_SCAREPEASANTS);
check_flag(tc, "cansteal", RCF_CANSTEAL);
check_flag(tc, "nosteal", RCF_NOSTEAL);
check_flag(tc, "noheal", RCF_NOHEAL);
check_flag(tc, "undead", RCF_UNDEAD);
check_flag(tc, "dragon", RCF_DRAGON);
check_flag(tc, "fly", RCF_FLY);
check_ec_flag(tc, "getitem", GETITEM);
check_ec_flag(tc, "giveitem", GIVEITEM);
check_ec_flag(tc, "giveperson", GIVEPERSON);
check_ec_flag(tc, "giveunit", GIVEUNIT);
test_cleanup();
}
@ -56,7 +68,7 @@ static void test_races(CuTest * tc)
"\"capacity\" : 4,"
"\"hp\" : 5,"
"\"ac\" : 6,"
"\"flags\" : [ \"playerrace\", \"walk\", \"undead\" ]"
"\"flags\" : [ \"npc\", \"walk\", \"undead\" ]"
"}}}";
cJSON *json = cJSON_Parse(data);
const struct race *rc;
@ -70,7 +82,7 @@ static void test_races(CuTest * tc)
CuAssertPtrNotNull(tc, races);
rc = rc_find("orc");
CuAssertPtrNotNull(tc, rc);
CuAssertIntEquals(tc, RCF_PLAYERRACE|RCF_WALK|RCF_UNDEAD, rc->flags);
CuAssertIntEquals(tc, RCF_NPC|RCF_WALK|RCF_UNDEAD, rc->flags);
CuAssertStrEquals(tc, "1d4", rc->def_damage);
CuAssertDblEquals(tc, 1.0, rc->magres, 0.0);
CuAssertDblEquals(tc, 2.0, rc->maxaura, 0.0);

View file

@ -183,11 +183,11 @@ extern "C" {
const struct weapon_type *);
void free_races(void);
/* Flags */
#define RCF_PLAYERRACE (1<<0) /* can be played by a player. */
#define RCF_KILLPEASANTS (1<<1) /* Töten Bauern. Dämonen werden nicht über dieses Flag, sondern in randenc() behandelt. */
#define RCF_SCAREPEASANTS (1<<2)
#define RCF_CANSTEAL (1<<3)
/* Flags. Do not reorder these without changing json_race() in jsonconf.c */
#define RCF_NPC (1<<0) /* cannot be the race for a player faction (and other limits?) */
#define RCF_KILLPEASANTS (1<<1) /* a monster that eats peasants */
#define RCF_SCAREPEASANTS (1<<2) /* a monster that scares peasants out of the hex */
#define RCF_NOSTEAL (1<<3) /* this race has high stealth, but is not allowed to steal */
#define RCF_MOVERANDOM (1<<4)
#define RCF_CANNOTMOVE (1<<5)
#define RCF_LEARN (1<<6) /* Lernt automatisch wenn struct faction == 0 */
@ -238,7 +238,7 @@ extern "C" {
#define omniscient(f) ((f)->race==get_race(RC_ILLUSION) || (f)->race==get_race(RC_TEMPLATE))
#define playerrace(rc) (fval((rc), RCF_PLAYERRACE))
#define playerrace(rc) (!fval((rc), RCF_NPC))
#define dragonrace(rc) ((rc) == get_race(RC_FIREDRAGON) || (rc) == get_race(RC_DRAGON) || (rc) == get_race(RC_WYRM) || (rc) == get_race(RC_BIRTHDAYDRAGON))
#define humanoidrace(rc) (fval((rc), RCF_UNDEAD) || (rc)==get_race(RC_DRACOID) || playerrace(rc))
#define illusionaryrace(rc) (fval(rc, RCF_ILLUSIONARY))

View file

@ -27,41 +27,38 @@ extern "C" {
#include "direction.h"
/* FAST_CONNECT: regions are directly connected to neighbours, saves doing
a hash-access each time a neighbour is needed */
a hash-access each time a neighbour is needed, 6 extra pointers per hex */
#define FAST_CONNECT
#define RF_CHAOTIC (1<<0)
#define RF_MALLORN (1<<1)
#define RF_BLOCKED (1<<2)
#define RF_CHAOTIC (1<<0) /* persistent */
#define RF_MALLORN (1<<1) /* persistent */
#define RF_BLOCKED (1<<2) /* persistent */
#define RF_BLOCK_NORTHWEST (1<<3)
#define RF_BLOCK_NORTHEAST (1<<4)
#define RF_BLOCK_EAST (1<<5)
#define RF_BLOCK_SOUTHEAST (1<<6)
#define RF_BLOCK_SOUTHWEST (1<<7)
#define RF_BLOCK_WEST (1<<8)
#define RF_UNUSED_3 (1<<3)
#define RF_UNUSED_4 (1<<4)
#define RF_UNUSED_5 (1<<5)
#define RF_UNUSED_6 (1<<6)
#define RF_UNUSED_7 (1<<7)
#define RF_UNUSED_8 (1<<8)
#define RF_ENCOUNTER (1<<9)
#define RF_MIGRATION (1<<10)
#define RF_UNUSED_1 (1<<11)
#define RF_ORCIFIED (1<<12)
#define RF_CURSED (1<<13)
#define RF_ENCOUNTER (1<<9) /* persistent */
#define RF_MAPPER_HIGHLIGHT (1<<10)
#define RF_LIGHTHOUSE (1<<11) /* this region may contain a lighthouse */
#define RF_ORCIFIED (1<<12) /* persistent */
#define RF_MIGRATION (1<<13)
/* debug flags */
#define RF_COMBATDEBUG (1<<14)
#define RF_MAPPER_HIGHLIGHT (1<<14) /* only used by mapper, not stored */
#define RF_LIGHTHOUSE (1<<15) /* this region may contain a lighthouse */
#define RF_UNUSED_14 (1<<14)
#define RF_UNUSED_15 (1<<15)
#define RF_UNUSED_16 (1<<16)
#define RF_SELECT (1<<17)
#define RF_MARK (1<<18)
/* flags that speed up attribute access: */
#define RF_TRAVELUNIT (1<<19)
#define RF_GUARDED (1<<20)
#define RF_GUARDED (1<<20) /* persistent */
#define RF_ALL 0xFFFFFF
#define RF_SAVEMASK (RF_GUARDED|RF_CHAOTIC|RF_MALLORN|RF_BLOCKED|RF_BLOCK_NORTHWEST|RF_BLOCK_NORTHEAST|RF_BLOCK_EAST|RF_BLOCK_SOUTHEAST|RF_BLOCK_SOUTHWEST|RF_BLOCK_WEST|RF_ENCOUNTER|RF_ORCIFIED)
#define RF_SAVEMASK (RF_CHAOTIC|RF_MALLORN|RF_BLOCKED|RF_ENCOUNTER|RF_ORCIFIED|RF_GUARDED)
struct message;
struct message_list;
struct rawmaterial;

View file

@ -1214,8 +1214,8 @@ bool has_skill(const unit * u, skill_t sk)
static int item_invis(const unit *u) {
const struct resource_type *rring = get_resourcetype(R_RING_OF_INVISIBILITY);
const struct resource_type *rsphere = get_resourcetype(R_SPHERE_OF_INVISIBILITY);
return i_get(u->items, rring->itype)
+ i_get(u->items, rsphere->itype) * 100;
return (rring ? i_get(u->items, rring->itype) : 0)
+ (rsphere ? i_get(u->items, rsphere->itype) * 100 : 0);
}
static int item_modification(const unit * u, skill_t sk, int val)

View file

@ -30,7 +30,7 @@ extern "C" {
struct item;
struct sc_mage;
#define UFL_DEBUG (1<<0)
#define UFL_DEAD (1<<0)
#define UFL_ISNEW (1<<1) /* 2 */
#define UFL_LONGACTION (1<<2) /* 4 */
#define UFL_OWNER (1<<3) /* 8 */

View file

@ -1668,12 +1668,12 @@ static int parse_races(xmlDocPtr doc)
rc->at_bonus = (char)xml_ivalue(node, "attackmodifier", 0);
rc->df_bonus = (char)xml_ivalue(node, "defensemodifier", 0);
if (xml_bvalue(node, "playerrace", false))
rc->flags |= RCF_PLAYERRACE;
if (!xml_bvalue(node, "playerrace", false))
rc->flags |= RCF_NPC;
if (xml_bvalue(node, "scarepeasants", false))
rc->flags |= RCF_SCAREPEASANTS;
if (xml_bvalue(node, "cansteal", true))
rc->flags |= RCF_CANSTEAL;
if (!xml_bvalue(node, "cansteal", true))
rc->flags |= RCF_NOSTEAL;
if (xml_bvalue(node, "cansail", true))
rc->flags |= RCF_CANSAIL;
if (xml_bvalue(node, "cannotmove", false))

View file

@ -1,7 +1,10 @@
#include <platform.h>
#include <kernel/config.h>
#include <CuTest.h>
#include <stdio.h>
#include <util/log.h>
CuSuite *get_tests_suite(void);
CuSuite *get_callback_suite(void);
CuSuite *get_jsonconf_suite(void);
@ -39,6 +42,7 @@ int RunAllTests(void)
int flags = log_flags;
log_flags = LOG_FLUSH | LOG_CPERROR;
kernel_init();
/* self-test */
CuSuiteAddSuite(suite, get_tests_suite());

View file

@ -25,7 +25,6 @@
struct race *test_create_race(const char *name)
{
race *rc = rc_get_or_create(name);
rc->flags |= RCF_PLAYERRACE;
rc->maintenance = 10;
return rc;
}

View file

@ -189,8 +189,7 @@ void locale_setstring(locale * lang, const char *key, const char *value)
const char *locale_name(const locale * lang)
{
assert(lang);
return lang->name;
return lang ? lang->name : "(null)";
}
char *mkname_buf(const char *space, const char *name, char *buffer)

View file

@ -1,4 +1,5 @@
-- new tests 2014-06-11
require "tests.pool"
require "tests.settings"
require "tests.config"
require "tests.locale"
@ -8,3 +9,4 @@ require "tests.castles"
require "tests.spells"
require "tests.movement"
require "tests.ships"
require "tests.pool"

74
tests/pool.lua Normal file
View file

@ -0,0 +1,74 @@
require "lunit"
module("tests.eressea.pool", package.seeall, lunit.testcase )
function setup()
eressea.free_game()
eressea.config.reset();
eressea.settings.set("rules.economy.food", "0")
eressea.settings.set("nmr.removenewbie", "0")
eressea.settings.set("nmr.timeout", "0")
conf = [[{
"races": {
"human" : { "flags" : [ "giveitem", "getitem" ] }
},
"terrains" : {
"plain": { "flags" : [ "land" ] }
},
"keywords" : {
"de" : {
"give" : "GIB",
"contact" : "KONTAKTIERE"
}
},
"strings" : {
"de" : {
"money" : "Silber"
}
}
}]]
assert(eressea.config.parse(conf)==0)
end
function test_give_nopool()
local r = region.create(1, 1, "plain")
local f = faction.create("test@example.com", "human", "de")
local u1 = unit.create(f, r, 1)
local u2 = unit.create(f, r, 1)
u1:add_item("money", 100)
u1:add_order("GIB " .. itoa36(u2.id) .. " 50 SILBER")
process_orders()
assert_equal(50, u1:get_item("money"))
assert_equal(50, u2:get_item("money"))
end
function test_give_from_faction()
local r = region.create(1, 1, "plain")
local f = faction.create("test@example.com", "human", "de")
local u1 = unit.create(f, r, 1)
local u2 = unit.create(f, r, 1)
local u3 = unit.create(f, r, 1)
u1:add_item("money", 50)
u2:add_item("money", 50)
u1:add_order("GIB " .. itoa36(u3.id) .. " 100 SILBER")
process_orders()
assert_equal(0, u1:get_item("money"))
assert_equal(0, u2:get_item("money"))
assert_equal(100, u3:get_item("money"))
end
function test_give_divisor()
eressea.settings.set("rules.items.give_divisor", 2)
local r = region.create(1, 1, "plain")
local f1 = faction.create("test@example.com", "human", "de")
local f2 = faction.create("test@example.com", "human", "de")
local u1 = unit.create(f1, r, 1)
local u2 = unit.create(f2, r, 1)
u2:add_order("KONTAKTIERE " .. itoa36(u1.id))
u1:add_item("money", 100)
u1:add_order("GIB " .. itoa36(u2.id) .. " 100 SILBER")
process_orders()
assert_equal(0, u1:get_item("money"))
assert_equal(50, u2:get_item("money"))
end