forked from github/server
Merge remote-tracking branch 'eressea/master'
This commit is contained in:
commit
c1c0689dc2
26 changed files with 395 additions and 210 deletions
|
@ -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"/>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#define VERSION_MAJOR 3
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_BUILD 677
|
||||
#define VERSION_BUILD 678
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
16
src/give.c
16
src/give.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
74
tests/pool.lua
Normal 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
|
Loading…
Reference in a new issue