forked from github/server
Merge pull request #230 from badgerman/feature-force-leave-postcombat
force leave after combat
This commit is contained in:
commit
9d1eac2f6a
|
@ -36,4 +36,3 @@ function test_read_ship()
|
||||||
s = ship.create(nil, "boat")
|
s = ship.create(nil, "boat")
|
||||||
assert_not_nil(s)
|
assert_not_nil(s)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,3 +7,4 @@ require 'tests.pool'
|
||||||
require 'tests.regions'
|
require 'tests.regions'
|
||||||
require 'tests.settings'
|
require 'tests.settings'
|
||||||
require 'tests.study'
|
require 'tests.study'
|
||||||
|
require 'tests.laws'
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
require "lunit"
|
||||||
|
|
||||||
|
module("tests.laws", package.seeall, lunit.testcase)
|
||||||
|
|
||||||
|
function setup()
|
||||||
|
eressea.free_game()
|
||||||
|
conf = [[{
|
||||||
|
"races": {
|
||||||
|
"human" : {}
|
||||||
|
},
|
||||||
|
"terrains" : {
|
||||||
|
"plain": { "flags" : [ "land", "walk", "sail" ] }
|
||||||
|
},
|
||||||
|
"keywords" : {
|
||||||
|
"de": {
|
||||||
|
"attack" : "ATTACKIERE",
|
||||||
|
"maketemp" : "MACHETEMP",
|
||||||
|
"end" : "ENDE",
|
||||||
|
"recruit" : "REKRUTIERE"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"buildings" : {
|
||||||
|
"castle" : {}
|
||||||
|
}
|
||||||
|
}]]
|
||||||
|
|
||||||
|
eressea.config.reset()
|
||||||
|
eressea.config.parse(conf)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_force_leave_on()
|
||||||
|
local r = region.create(0, 0, "plain")
|
||||||
|
local f1 = faction.create("owner@eressea.de")
|
||||||
|
local f2 = faction.create("guest@eressea.de")
|
||||||
|
local u1 = unit.create(f1, r, 1)
|
||||||
|
local u2 = unit.create(f2, r, 1)
|
||||||
|
local b1 = building.create(r, "castle")
|
||||||
|
u1.building = b1
|
||||||
|
u2.building = b1
|
||||||
|
eressea.settings.set("rules.owners.force_leave", "2")
|
||||||
|
process_orders()
|
||||||
|
assert_equal(b1, u1.building)
|
||||||
|
assert_equal(nil, u2.building)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_force_leave_off()
|
||||||
|
local r = region.create(0, 0, "plain")
|
||||||
|
local f1 = faction.create("owner@eressea.de")
|
||||||
|
local f2 = faction.create("guest@eressea.de")
|
||||||
|
local u1 = unit.create(f1, r, 1)
|
||||||
|
local u2 = unit.create(f2, r, 1)
|
||||||
|
local b1 = building.create(r, "castle")
|
||||||
|
u1.building = b1
|
||||||
|
u2.building = b1
|
||||||
|
eressea.settings.set("rules.owners.force_leave", "0")
|
||||||
|
process_orders()
|
||||||
|
assert_equal(b1, u1.building)
|
||||||
|
assert_equal(b1, u2.building)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_make_temp()
|
||||||
|
local r = region.create(0, 0, "plain")
|
||||||
|
local f1 = faction.create("owner@eressea.de", "human", "de")
|
||||||
|
local u1 = unit.create(f1, r, 10)
|
||||||
|
local u, u2
|
||||||
|
|
||||||
|
u1.building = building.create(r, "castle")
|
||||||
|
u1.status = 1
|
||||||
|
u1:clear_orders()
|
||||||
|
u1:add_order("MACHETEMP 1 Hodor")
|
||||||
|
u1:add_order("REKRUTIERE 1")
|
||||||
|
u1:add_order("ENDE")
|
||||||
|
process_orders()
|
||||||
|
for u in r.units do
|
||||||
|
if u~=u1 then
|
||||||
|
u2 = u
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assert_not_equal(nil, u2)
|
||||||
|
assert_not_equal(nil, u2.building)
|
||||||
|
assert_equal(1, u2.number)
|
||||||
|
assert_equal(1, u2.status)
|
||||||
|
assert_equal("Hodor", u2.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_force_leave_postcombat()
|
||||||
|
local r = region.create(0, 0, "plain")
|
||||||
|
local f1 = faction.create("owner@eressea.de", "human", "de")
|
||||||
|
local f2 = faction.create("guest@eressea.de", "human", "de")
|
||||||
|
local u1 = unit.create(f1, r, 10)
|
||||||
|
local u2 = unit.create(f2, r, 10)
|
||||||
|
local u, u3
|
||||||
|
local b1 = building.create(r, "castle")
|
||||||
|
u1.building = b1
|
||||||
|
u2.building = b1
|
||||||
|
eressea.settings.set("rules.owners.force_leave", "1")
|
||||||
|
u1:clear_orders()
|
||||||
|
u1:add_order("ATTACKIERE " .. itoa36(u2.id))
|
||||||
|
u2:clear_orders()
|
||||||
|
u2:add_order("MACHETEMP 2 Hodor")
|
||||||
|
u2:add_order("REKRUTIERE 1")
|
||||||
|
u2:add_order("ENDE")
|
||||||
|
process_orders()
|
||||||
|
for u in r.units do
|
||||||
|
if u~=u1 and u~=u2 then
|
||||||
|
u3 = u
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assert_not_equal(nil, u3)
|
||||||
|
assert_equal(nil, u3.building)
|
||||||
|
assert_equal(1, u3.number)
|
||||||
|
end
|
|
@ -3946,7 +3946,6 @@ static bool start_battle(region * r, battle ** bp)
|
||||||
unit *u;
|
unit *u;
|
||||||
bool fighting = false;
|
bool fighting = false;
|
||||||
|
|
||||||
/* list_foreach geht nicht, wegen flucht */
|
|
||||||
for (u = r->units; u != NULL; u = u->next) {
|
for (u = r->units; u != NULL; u = u->next) {
|
||||||
if (fval(u, UFL_LONGACTION))
|
if (fval(u, UFL_LONGACTION))
|
||||||
continue;
|
continue;
|
||||||
|
@ -4307,6 +4306,9 @@ void do_battle(region * r)
|
||||||
|
|
||||||
/* Auswirkungen berechnen: */
|
/* Auswirkungen berechnen: */
|
||||||
aftermath(b);
|
aftermath(b);
|
||||||
|
if (rule_force_leave(FORCE_LEAVE_POSTCOMBAT)) {
|
||||||
|
force_leave(b->region);
|
||||||
|
}
|
||||||
/* Hier ist das Gefecht beendet, und wir können die
|
/* Hier ist das Gefecht beendet, und wir können die
|
||||||
* Hilfsstrukturen * wieder löschen: */
|
* Hilfsstrukturen * wieder löschen: */
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ without prior permission by the authors of Eressea.
|
||||||
#include <kernel/building.h>
|
#include <kernel/building.h>
|
||||||
#include <kernel/region.h>
|
#include <kernel/region.h>
|
||||||
|
|
||||||
|
#include <util/log.h>
|
||||||
#include <util/language.h>
|
#include <util/language.h>
|
||||||
|
|
||||||
#include <tolua.h>
|
#include <tolua.h>
|
||||||
|
@ -190,6 +191,12 @@ static int tolua_building_create(lua_State * L)
|
||||||
{
|
{
|
||||||
region *r = (region *)tolua_tousertype(L, 1, 0);
|
region *r = (region *)tolua_tousertype(L, 1, 0);
|
||||||
const char *bname = tolua_tostring(L, 2, 0);
|
const char *bname = tolua_tostring(L, 2, 0);
|
||||||
|
if (!r) {
|
||||||
|
log_error("building.create expects a region as argument 1");
|
||||||
|
}
|
||||||
|
if (!bname) {
|
||||||
|
log_error("building.create expects a name as argument 2");
|
||||||
|
}
|
||||||
if (bname) {
|
if (bname) {
|
||||||
const building_type *btype = bt_find(bname);
|
const building_type *btype = bt_find(bname);
|
||||||
if (btype) {
|
if (btype) {
|
||||||
|
|
|
@ -991,7 +991,7 @@ void init_locale(struct locale *lang)
|
||||||
addtoken(tokens, name, var);
|
addtoken(tokens, name, var);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log_error("no translation for magic school %s in locale %s", tok, locale_name(lang));
|
log_warning("no translation for magic school %s in locale %s", tok, locale_name(lang));
|
||||||
}
|
}
|
||||||
tok = strtok(NULL, " ");
|
tok = strtok(NULL, " ");
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,6 +183,7 @@ race *rc_get_or_create(const char *zName)
|
||||||
rc->recruit_multi = 1.0F;
|
rc->recruit_multi = 1.0F;
|
||||||
rc->regaura = 1.0F;
|
rc->regaura = 1.0F;
|
||||||
rc->speed = 1.0F;
|
rc->speed = 1.0F;
|
||||||
|
rc->battle_flags = BF_CANATTACK;
|
||||||
if (strchr(zName, ' ') != NULL) {
|
if (strchr(zName, ' ') != NULL) {
|
||||||
log_error("race '%s' has an invalid name. remove spaces\n", zName);
|
log_error("race '%s' has an invalid name. remove spaces\n", zName);
|
||||||
assert(strchr(zName, ' ') == NULL);
|
assert(strchr(zName, ' ') == NULL);
|
||||||
|
|
|
@ -1726,7 +1726,7 @@ static int parse_races(xmlDocPtr doc)
|
||||||
if (xml_bvalue(node, "resistpierce", false))
|
if (xml_bvalue(node, "resistpierce", false))
|
||||||
rc->battle_flags |= BF_RES_PIERCE;
|
rc->battle_flags |= BF_RES_PIERCE;
|
||||||
if (xml_bvalue(node, "canattack", true))
|
if (xml_bvalue(node, "canattack", true))
|
||||||
rc->battle_flags |= BF_CANATTACK;
|
rc->battle_flags |= BF_CANATTACK; // TODO: invert this flag, so rc_get_or_create gets simpler
|
||||||
|
|
||||||
for (child = node->children; child; child = child->next) {
|
for (child = node->children; child; child = child->next) {
|
||||||
if (strcmp((const char *)child->name, "ai") == 0) {
|
if (strcmp((const char *)child->name, "ai") == 0) {
|
||||||
|
|
21
src/laws.c
21
src/laws.c
|
@ -3346,7 +3346,7 @@ void new_units(void)
|
||||||
}
|
}
|
||||||
u2 = create_unit(r, u->faction, 0, u->faction->race, alias, name, u);
|
u2 = create_unit(r, u->faction, 0, u->faction->race, alias, name, u);
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
free(name);
|
free(name); // TODO: use a buffer on the stack instead?
|
||||||
fset(u2, UFL_ISNEW);
|
fset(u2, UFL_ISNEW);
|
||||||
|
|
||||||
a_add(&u2->attribs, a_new(&at_alias))->data.i = alias;
|
a_add(&u2->attribs, a_new(&at_alias))->data.i = alias;
|
||||||
|
@ -4337,6 +4337,11 @@ void force_leave(region *r) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rule_force_leave(int flags) {
|
||||||
|
int rules = get_param_int(global.parameters, "rules.owners.force_leave", 0);
|
||||||
|
return (rules&flags) == flags;
|
||||||
|
}
|
||||||
|
|
||||||
static void maintain_buildings_1(region * r)
|
static void maintain_buildings_1(region * r)
|
||||||
{
|
{
|
||||||
maintain_buildings(r, false);
|
maintain_buildings(r, false);
|
||||||
|
@ -4373,6 +4378,12 @@ void init_processor(void)
|
||||||
{
|
{
|
||||||
int p;
|
int p;
|
||||||
|
|
||||||
|
while (processors) {
|
||||||
|
processor * next = processors->next;
|
||||||
|
free(processors);
|
||||||
|
processors = next;
|
||||||
|
}
|
||||||
|
|
||||||
p = 10;
|
p = 10;
|
||||||
add_proc_global(p, new_units, "Neue Einheiten erschaffen");
|
add_proc_global(p, new_units, "Neue Einheiten erschaffen");
|
||||||
|
|
||||||
|
@ -4438,7 +4449,7 @@ void init_processor(void)
|
||||||
add_proc_unit(p, follow_unit, "Folge auf Einheiten setzen");
|
add_proc_unit(p, follow_unit, "Folge auf Einheiten setzen");
|
||||||
|
|
||||||
p += 10; /* rest rng again before economics */
|
p += 10; /* rest rng again before economics */
|
||||||
if (get_param_int(global.parameters, "rules.owners.force_leave", 0)) {
|
if (rule_force_leave(FORCE_LEAVE_ALL)) {
|
||||||
add_proc_region(p, force_leave, "kick non-allies out of buildings/ships");
|
add_proc_region(p, force_leave, "kick non-allies out of buildings/ships");
|
||||||
}
|
}
|
||||||
add_proc_region(p, economics, "Zerstoeren, Geben, Rekrutieren, Vergessen");
|
add_proc_region(p, economics, "Zerstoeren, Geben, Rekrutieren, Vergessen");
|
||||||
|
@ -4523,12 +4534,8 @@ void init_processor(void)
|
||||||
|
|
||||||
void processorders(void)
|
void processorders(void)
|
||||||
{
|
{
|
||||||
static int init = 0;
|
|
||||||
|
|
||||||
if (!init) {
|
|
||||||
init_processor();
|
init_processor();
|
||||||
init = 1;
|
|
||||||
}
|
|
||||||
update_spells();
|
update_spells();
|
||||||
process();
|
process();
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
|
|
|
@ -105,9 +105,13 @@ extern "C" {
|
||||||
bool seefaction(const struct faction *f, const struct region *r,
|
bool seefaction(const struct faction *f, const struct region *r,
|
||||||
const struct unit *u, int modifier);
|
const struct unit *u, int modifier);
|
||||||
int armedmen(const struct unit *u, bool siege_weapons);
|
int armedmen(const struct unit *u, bool siege_weapons);
|
||||||
void force_leave(struct region *r);
|
|
||||||
int peasant_luck_effect(int peasants, int luck, int maxp, double variance);
|
int peasant_luck_effect(int peasants, int luck, int maxp, double variance);
|
||||||
|
|
||||||
|
#define FORCE_LEAVE_POSTCOMBAT 1
|
||||||
|
#define FORCE_LEAVE_ALL 2
|
||||||
|
bool rule_force_leave(int flag);
|
||||||
|
void force_leave(struct region *r);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -230,6 +230,21 @@ static void test_display_cmd(CuTest *tc) {
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_rule_force_leave(CuTest *tc) {
|
||||||
|
set_param(&global.parameters, "rules.owners.force_leave", "0");
|
||||||
|
CuAssertIntEquals(tc, false, rule_force_leave(FORCE_LEAVE_ALL));
|
||||||
|
CuAssertIntEquals(tc, false, rule_force_leave(FORCE_LEAVE_POSTCOMBAT));
|
||||||
|
set_param(&global.parameters, "rules.owners.force_leave", "1");
|
||||||
|
CuAssertIntEquals(tc, false, rule_force_leave(FORCE_LEAVE_ALL));
|
||||||
|
CuAssertIntEquals(tc, true, rule_force_leave(FORCE_LEAVE_POSTCOMBAT));
|
||||||
|
set_param(&global.parameters, "rules.owners.force_leave", "2");
|
||||||
|
CuAssertIntEquals(tc, true, rule_force_leave(FORCE_LEAVE_ALL));
|
||||||
|
CuAssertIntEquals(tc, false, rule_force_leave(FORCE_LEAVE_POSTCOMBAT));
|
||||||
|
set_param(&global.parameters, "rules.owners.force_leave", "3");
|
||||||
|
CuAssertIntEquals(tc, true, rule_force_leave(FORCE_LEAVE_ALL));
|
||||||
|
CuAssertIntEquals(tc, true, rule_force_leave(FORCE_LEAVE_POSTCOMBAT));
|
||||||
|
}
|
||||||
|
|
||||||
static void test_force_leave_buildings(CuTest *tc) {
|
static void test_force_leave_buildings(CuTest *tc) {
|
||||||
ally *al;
|
ally *al;
|
||||||
region *r;
|
region *r;
|
||||||
|
@ -779,6 +794,7 @@ CuSuite *get_laws_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_enter_building);
|
SUITE_ADD_TEST(suite, test_enter_building);
|
||||||
SUITE_ADD_TEST(suite, test_enter_ship);
|
SUITE_ADD_TEST(suite, test_enter_ship);
|
||||||
SUITE_ADD_TEST(suite, test_display_cmd);
|
SUITE_ADD_TEST(suite, test_display_cmd);
|
||||||
|
SUITE_ADD_TEST(suite, test_rule_force_leave);
|
||||||
SUITE_ADD_TEST(suite, test_force_leave_buildings);
|
SUITE_ADD_TEST(suite, test_force_leave_buildings);
|
||||||
SUITE_ADD_TEST(suite, test_force_leave_ships);
|
SUITE_ADD_TEST(suite, test_force_leave_ships);
|
||||||
SUITE_ADD_TEST(suite, test_force_leave_ships_on_ocean);
|
SUITE_ADD_TEST(suite, test_force_leave_ships_on_ocean);
|
||||||
|
|
|
@ -114,8 +114,18 @@ const char *combatstatus[] = {
|
||||||
const char *report_kampfstatus(const unit * u, const struct locale *lang)
|
const char *report_kampfstatus(const unit * u, const struct locale *lang)
|
||||||
{
|
{
|
||||||
static char fsbuf[64]; // FIXME: static return value
|
static char fsbuf[64]; // FIXME: static return value
|
||||||
|
const char * status = LOC(lang, combatstatus[u->status]);
|
||||||
|
|
||||||
strlcpy(fsbuf, LOC(lang, combatstatus[u->status]), sizeof(fsbuf));
|
if (!status) {
|
||||||
|
const char *lname = locale_name(lang);
|
||||||
|
struct locale *wloc = get_or_create_locale(lname);
|
||||||
|
log_error("no translation for combat status %s in %s", combatstatus[u->status], lname);
|
||||||
|
locale_setstring(wloc, combatstatus[u->status], combatstatus[u->status]);
|
||||||
|
strlcpy(fsbuf, combatstatus[u->status], sizeof(fsbuf));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strlcpy(fsbuf, status, sizeof(fsbuf));
|
||||||
|
}
|
||||||
if (fval(u, UFL_NOAID)) {
|
if (fval(u, UFL_NOAID)) {
|
||||||
strcat(fsbuf, ", ");
|
strcat(fsbuf, ", ");
|
||||||
strcat(fsbuf, LOC(lang, "status_noaid"));
|
strcat(fsbuf, LOC(lang, "status_noaid"));
|
||||||
|
|
|
@ -31,6 +31,7 @@ size_t strlcpy(char *dst, const char *src, size_t siz)
|
||||||
register const char *s = src;
|
register const char *s = src;
|
||||||
register size_t n = siz;
|
register size_t n = siz;
|
||||||
|
|
||||||
|
assert(src && dst);
|
||||||
/* Copy as many bytes as will fit */
|
/* Copy as many bytes as will fit */
|
||||||
if (n != 0 && --n != 0) {
|
if (n != 0 && --n != 0) {
|
||||||
do {
|
do {
|
||||||
|
|
Loading…
Reference in New Issue