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")
|
||||
assert_not_nil(s)
|
||||
end
|
||||
|
||||
|
|
|
@ -7,3 +7,4 @@ require 'tests.pool'
|
|||
require 'tests.regions'
|
||||
require 'tests.settings'
|
||||
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;
|
||||
bool fighting = false;
|
||||
|
||||
/* list_foreach geht nicht, wegen flucht */
|
||||
for (u = r->units; u != NULL; u = u->next) {
|
||||
if (fval(u, UFL_LONGACTION))
|
||||
continue;
|
||||
|
@ -4307,6 +4306,9 @@ void do_battle(region * r)
|
|||
|
||||
/* Auswirkungen berechnen: */
|
||||
aftermath(b);
|
||||
if (rule_force_leave(FORCE_LEAVE_POSTCOMBAT)) {
|
||||
force_leave(b->region);
|
||||
}
|
||||
/* Hier ist das Gefecht beendet, und wir können die
|
||||
* Hilfsstrukturen * wieder löschen: */
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ without prior permission by the authors of Eressea.
|
|||
#include <kernel/building.h>
|
||||
#include <kernel/region.h>
|
||||
|
||||
#include <util/log.h>
|
||||
#include <util/language.h>
|
||||
|
||||
#include <tolua.h>
|
||||
|
@ -190,6 +191,12 @@ static int tolua_building_create(lua_State * L)
|
|||
{
|
||||
region *r = (region *)tolua_tousertype(L, 1, 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) {
|
||||
const building_type *btype = bt_find(bname);
|
||||
if (btype) {
|
||||
|
|
|
@ -991,7 +991,7 @@ void init_locale(struct locale *lang)
|
|||
addtoken(tokens, name, var);
|
||||
}
|
||||
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, " ");
|
||||
}
|
||||
|
|
|
@ -183,6 +183,7 @@ race *rc_get_or_create(const char *zName)
|
|||
rc->recruit_multi = 1.0F;
|
||||
rc->regaura = 1.0F;
|
||||
rc->speed = 1.0F;
|
||||
rc->battle_flags = BF_CANATTACK;
|
||||
if (strchr(zName, ' ') != NULL) {
|
||||
log_error("race '%s' has an invalid name. remove spaces\n", zName);
|
||||
assert(strchr(zName, ' ') == NULL);
|
||||
|
|
|
@ -1726,7 +1726,7 @@ static int parse_races(xmlDocPtr doc)
|
|||
if (xml_bvalue(node, "resistpierce", false))
|
||||
rc->battle_flags |= BF_RES_PIERCE;
|
||||
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) {
|
||||
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);
|
||||
if (name != NULL)
|
||||
free(name);
|
||||
free(name); // TODO: use a buffer on the stack instead?
|
||||
fset(u2, UFL_ISNEW);
|
||||
|
||||
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)
|
||||
{
|
||||
maintain_buildings(r, false);
|
||||
|
@ -4373,6 +4378,12 @@ void init_processor(void)
|
|||
{
|
||||
int p;
|
||||
|
||||
while (processors) {
|
||||
processor * next = processors->next;
|
||||
free(processors);
|
||||
processors = next;
|
||||
}
|
||||
|
||||
p = 10;
|
||||
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");
|
||||
|
||||
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, economics, "Zerstoeren, Geben, Rekrutieren, Vergessen");
|
||||
|
@ -4523,12 +4534,8 @@ void init_processor(void)
|
|||
|
||||
void processorders(void)
|
||||
{
|
||||
static int init = 0;
|
||||
|
||||
if (!init) {
|
||||
init_processor();
|
||||
init = 1;
|
||||
}
|
||||
|
||||
update_spells();
|
||||
process();
|
||||
/*************************************************/
|
||||
|
|
|
@ -105,9 +105,13 @@ extern "C" {
|
|||
bool seefaction(const struct faction *f, const struct region *r,
|
||||
const struct unit *u, int modifier);
|
||||
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);
|
||||
|
||||
#define FORCE_LEAVE_POSTCOMBAT 1
|
||||
#define FORCE_LEAVE_ALL 2
|
||||
bool rule_force_leave(int flag);
|
||||
void force_leave(struct region *r);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -230,6 +230,21 @@ static void test_display_cmd(CuTest *tc) {
|
|||
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) {
|
||||
ally *al;
|
||||
region *r;
|
||||
|
@ -779,6 +794,7 @@ CuSuite *get_laws_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_enter_building);
|
||||
SUITE_ADD_TEST(suite, test_enter_ship);
|
||||
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_ships);
|
||||
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)
|
||||
{
|
||||
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)) {
|
||||
strcat(fsbuf, ", ");
|
||||
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 size_t n = siz;
|
||||
|
||||
assert(src && dst);
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0 && --n != 0) {
|
||||
do {
|
||||
|
|
Loading…
Reference in New Issue