Merge pull request #230 from badgerman/feature-force-leave-postcombat

force leave after combat
This commit is contained in:
Enno Rehling 2015-06-19 15:03:30 +02:00
commit 9d1eac2f6a
13 changed files with 177 additions and 15 deletions

View File

@ -36,4 +36,3 @@ function test_read_ship()
s = ship.create(nil, "boat")
assert_not_nil(s)
end

View File

@ -7,3 +7,4 @@ require 'tests.pool'
require 'tests.regions'
require 'tests.settings'
require 'tests.study'
require 'tests.laws'

114
scripts/tests/laws.lua Normal file
View File

@ -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

View File

@ -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: */

View File

@ -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,7 +191,13 @@ 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 (bname) {
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) {
building *b = new_building(btype, r, default_locale);

View File

@ -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, " ");
}

View File

@ -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);

View File

@ -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) {

View File

@ -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,13 +4534,9 @@ void init_processor(void)
void processorders(void)
{
static int init = 0;
init_processor();
if (!init) {
init_processor();
init = 1;
}
update_spells();
update_spells();
process();
/*************************************************/

View File

@ -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

View File

@ -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);

View File

@ -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"));

View File

@ -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 {