Merge pull request #61 from badgerman/master

miscellaneous refactoring
This commit is contained in:
Enno Rehling 2014-12-10 20:14:25 +01:00
commit ba23a8bb06
30 changed files with 206 additions and 426 deletions

View File

@ -84,6 +84,7 @@ set (ERESSEA_SRC
laws.c
magic.c
market.c
morale.c
monster.c
randenc.c
report.c

View File

@ -215,10 +215,6 @@ static int age_potiondelay(attrib * a)
return AT_AGE_REMOVE;
}
/* TODO:
* - this should be a more general item_delay
* - it should not just happen in age(), but be done with eventhandling
*/
attrib_type at_potiondelay = {
"potiondelay",
init_potiondelay,

View File

@ -4,7 +4,6 @@ stealth.test.c
)
SET(_FILES
alliance.c
attributes.c
fleechance.c
follow.c

View File

@ -1,33 +0,0 @@
/*
Copyright (c) 1998-2010, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
#include <platform.h>
#include "alliance.h"
#include <kernel/save.h>
#include <util/attrib.h>
attrib_type at_alliance = {
"alliance",
NULL,
NULL,
NULL,
a_writeint,
a_readint,
ATF_UNIQUE
};

View File

@ -1,7 +1,7 @@
/*
Copyright (c) 1998-2010, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -37,9 +37,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "raceprefix.h"
#include "reduceproduction.h"
#include "targetregion.h"
#ifdef WDW_PYRAMID
# include "alliance.h"
#endif
/* kernel includes */
#include <kernel/unit.h>
@ -53,30 +50,26 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/attrib.h>
attrib_type at_unitdissolve = {
"unitdissolve", NULL, NULL, NULL, a_writechars, a_readchars
"unitdissolve", NULL, NULL, NULL, a_writechars, a_readchars
};
void register_attributes(void)
{
at_register(&at_stealth);
at_register(&at_object);
at_register(&at_unitdissolve);
at_register(&at_overrideroads);
at_register(&at_raceprefix);
at_register(&at_iceberg);
at_register(&at_key);
at_register(&at_gm);
at_register(&at_follow);
at_register(&at_targetregion);
at_register(&at_orcification);
at_register(&at_hate);
at_register(&at_reduceproduction);
at_register(&at_otherfaction);
at_register(&at_racename);
at_register(&at_movement);
at_register(&at_moved);
#ifdef WDW_PYRAMID
at_register(&at_alliance);
#endif /* WDW_PYRAMID */
at_register(&at_unitdissolve);
at_register(&at_overrideroads);
at_register(&at_raceprefix);
at_register(&at_iceberg);
at_register(&at_key);
at_register(&at_gm);
at_register(&at_follow);
at_register(&at_targetregion);
at_register(&at_orcification);
at_register(&at_hate);
at_register(&at_reduceproduction);
at_register(&at_otherfaction);
at_register(&at_racename);
at_register(&at_movement);
at_register(&at_moved);
}

View File

@ -2052,9 +2052,6 @@ void dazzle(battle * b, troop * td)
td->fighter->person[td->index].defence--;
}
/* TODO: Gebäude/Schiffe sollten auch zerstörbar sein. Schwierig im Kampf,
* besonders bei Schiffen. */
void damage_building(battle * b, building * bldg, int damage_abs)
{
bldg->size = _max(1, bldg->size - damage_abs);
@ -2262,9 +2259,9 @@ static void attack(battle * b, troop ta, const att * a, int numattack)
ta.fighter->person[ta.index].last_action = b->turn;
}
if (td.fighter->unit->ship) {
/* FIXME should use damage_ship here? */
td.fighter->unit->ship->damage +=
DAMAGE_SCALE * dice_rand(a->data.dice);
int dice = dice_rand(a->data.dice);
ship * sh = td.fighter->unit->ship;
damage_ship(sh, dice / sh->type->damage / sh->size);
}
else if (td.fighter->unit->building) {
damage_building(b, td.fighter->unit->building, dice_rand(a->data.dice));
@ -3689,18 +3686,6 @@ static void free_battle(battle * b)
static int *get_alive(side * s)
{
#if 0
static int alive[NUMROWS];
fighter *fig;
memset(alive, 0, NUMROWS * sizeof(int));
for (fig = s->fighters; fig; fig = fig->next) {
if (fig->alive > 0) {
int row = statusrow(fig);
alive[row] += fig->alive;
}
}
return alive;
#endif
return s->size;
}

View File

@ -243,10 +243,6 @@ void tolua_building_open(lua_State * L)
tolua_variable(L, TOLUA_CAST "size", tolua_building_get_size,
tolua_building_set_size);
tolua_function(L, TOLUA_CAST "get_typename", tolua_building_get_typename);
#ifdef TODO
.property("type", &building_gettype)
.def_readwrite("size", &building::size)
#endif
tolua_variable(L, TOLUA_CAST "objects", tolua_building_get_objects, 0);
tolua_variable(L, TOLUA_CAST "working", tolua_building_get_working, tolua_building_set_working);

View File

@ -578,15 +578,6 @@ void tolua_faction_open(lua_State * L)
tolua_function(L, TOLUA_CAST "create", tolua_faction_create);
tolua_function(L, TOLUA_CAST "get", tolua_faction_get);
tolua_function(L, TOLUA_CAST "destroy", tolua_faction_destroy);
#ifdef TODO
def("faction_origin", &faction_getorigin,
pure_out_value(_2) + pure_out_value(_3)),.def_readwrite("subscription",
&faction::subscription)
.property("x", &faction_getorigin_x, &faction_setorigin_x)
.property("y", &faction_getorigin_y, &faction_setorigin_y)
#endif
tolua_function(L, TOLUA_CAST "add_notice", &tolua_faction_addnotice);
tolua_variable(L, TOLUA_CAST "objects", tolua_faction_get_objects,

View File

@ -219,7 +219,6 @@ void tolua_ship_open(lua_State * L)
.property("maxsize", &ship_maxsize)
.def_readwrite("damage", &ship::damage)
.def_readwrite("size", &ship::size)
.def_readwrite("coast", &ship::coast)
#endif
tolua_variable(L, TOLUA_CAST "objects", tolua_ship_get_objects, 0);

View File

@ -29,6 +29,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "spy.h"
#include "move.h"
#include "monster.h"
#include "morale.h"
#include "reports.h"
/* kernel includes */
@ -596,12 +597,8 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders)
static void friendly_takeover(region * r, faction * f)
{
int morale = region_get_morale(r);
region_set_owner(r, f, turn);
if (morale > 0) {
morale = _max(0, morale - MORALE_TRANSFER);
region_set_morale(r, morale, turn);
}
morale_change(r, MORALE_TRANSFER);
}
void give_control(unit * u, unit * u2)

View File

@ -1,6 +1,7 @@
project(kernel C)
SET(_TEST_FILES
alliance.test.c
build.test.c
config.test.c
group.test.c

View File

@ -43,12 +43,17 @@ without prior permission by the authors of Eressea.
alliance *alliances = NULL;
void free_alliance(alliance * al)
void free_alliances(void)
{
free(al->name);
if (al->members)
ql_free(al->members);
free(al);
while (alliances) {
alliance *al = alliances;
alliances = al->next;
free(al->name);
if (al->members) {
ql_free(al->members);
}
free(al);
}
}
alliance *makealliance(int id, const char *name)
@ -513,3 +518,7 @@ void alliance_setname(alliance * self, const char *name)
else
self->name = NULL;
}
bool is_allied(const struct faction *f1, const struct faction *f2) {
return (f1 == f2 || (f1->alliance && f1->alliance == f2->alliance));
}

View File

@ -57,9 +57,10 @@ extern "C" {
extern alliance *makealliance(int id, const char *name);
extern const char *alliancename(const struct alliance *al);
extern void setalliance(struct faction *f, alliance * al);
void free_alliance(struct alliance *al);
void free_alliances(void);
extern struct faction *alliance_get_leader(struct alliance *al);
extern void alliance_cmd(void);
bool is_allied(const struct faction *f1, const struct faction *f2);
void alliance_setname(alliance * self, const char *name);
/* execute commands */

View File

@ -0,0 +1,68 @@
#include <platform.h>
#include <kernel/config.h>
#include <kernel/faction.h>
#include "alliance.h"
#include <CuTest.h>
#include <tests.h>
#include <assert.h>
typedef struct alliance_fixture {
struct race * rc;
struct faction *f1, *f2;
} alliance_fixture;
static void setup_alliance(alliance_fixture *fix) {
test_cleanup();
test_create_world();
fix->rc = test_create_race("human");
fix->f1 = test_create_faction(fix->rc);
fix->f2 = test_create_faction(fix->rc);
assert(fix->rc && fix->f1 && fix->f2);
}
static void test_alliance_make(CuTest *tc) {
alliance * al;
test_cleanup();
assert(!alliances);
al = makealliance(1, "Hodor");
CuAssertPtrNotNull(tc, al);
CuAssertStrEquals(tc, "Hodor", al->name);
CuAssertIntEquals(tc, 1, al->id);
CuAssertIntEquals(tc, 0, al->flags);
CuAssertPtrEquals(tc, 0, al->members);
CuAssertPtrEquals(tc, 0, al->_leader);
CuAssertPtrEquals(tc, 0, al->allies);
CuAssertPtrEquals(tc, al, findalliance(1));
CuAssertPtrEquals(tc, al, alliances);
free_alliances();
CuAssertPtrEquals(tc, 0, findalliance(1));
CuAssertPtrEquals(tc, 0, alliances);
test_cleanup();
}
static void test_alliance_join(CuTest *tc) {
alliance_fixture fix;
alliance * al;
setup_alliance(&fix);
CuAssertPtrEquals(tc, 0, fix.f1->alliance);
CuAssertPtrEquals(tc, 0, fix.f2->alliance);
al = makealliance(1, "Hodor");
setalliance(fix.f1, al);
CuAssertPtrEquals(tc, fix.f1, alliance_get_leader(al));
setalliance(fix.f2, al);
CuAssertPtrEquals(tc, fix.f1, alliance_get_leader(al));
CuAssertTrue(tc, is_allied(fix.f1, fix.f2));
test_cleanup();
}
CuSuite *get_alliance_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_alliance_make);
SUITE_ADD_TEST(suite, test_alliance_join);
return suite;
}

View File

@ -65,7 +65,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* attributes inclues */
#include <attributes/matmod.h>
#include <attributes/alliance.h>
struct building *getbuilding(const struct region *r)
{
@ -775,12 +774,6 @@ build_building(unit * u, const building_type * btype, int id, int want, order *
if (u->number && leave(u, false)) {
u_set_building(u, b);
}
#ifdef WDW_PYRAMID
if (b->type == bt_find("pyramid") && f_get_alliance(u->faction) != NULL) {
attrib *a = a_add(&b->attribs, a_new(&at_alliance));
a->data.i = u->faction->alliance->id;
}
#endif
}
btname = LOC(lang, btype->_name);

View File

@ -270,45 +270,6 @@ static const char *fort_name(const struct building_type *btype,
return castle_name_i(btype, b, bsize, fname);
}
#ifdef WDW_PYRAMID
static const char *pyramid_name(const struct building_type *btype, int bsize)
{
static char p_name_buf[32];
int level = 0;
const construction *ctype;
ctype = btype->construction;
while (ctype && ctype->maxsize != -1 && ctype->maxsize <= bsize) {
bsize -= ctype->maxsize;
ctype = ctype->improvement;
++level;
}
sprintf(p_name_buf, "pyramid%d", level);
return p_name_buf;
}
int wdw_pyramid_level(const struct building *b)
{
const construction *ctype = b->type->construction;
int completed = b->size;
int level = 0;
while (ctype->improvement != NULL &&
ctype->improvement != ctype &&
ctype->maxsize > 0 && ctype->maxsize <= completed) {
++level;
completed -= ctype->maxsize;
ctype = ctype->improvement;
}
return level;
}
#endif
/* for finding out what was meant by a particular building string */
static local_names *bnames;
@ -371,9 +332,6 @@ void register_buildings(void)
register_function((pf_generic) & castle_name, "castle_name");
register_function((pf_generic) & castle_name_2, "castle_name_2");
register_function((pf_generic) & fort_name, "fort_name");
#ifdef WDW_PYRAMID
register_function((pf_generic) & pyramid_name, "pyramid_name");
#endif
}
void write_building_reference(const struct building *b, struct storage *store)

View File

@ -734,20 +734,6 @@ int alliedunit(const unit * u, const faction * f2, int mode)
return 0;
}
#ifndef NDEBUG
const char *strcheck(const char *s, size_t maxlen)
{
static char buffer[16 * 1024]; // FIXME: static return value
if (strlen(s) > maxlen) {
assert(maxlen < 16 * 1024);
log_warning("[strcheck] string was shortened to %d bytes:\n%s\n", (int)maxlen, s);
strlcpy(buffer, s, maxlen);
return buffer;
}
return s;
}
#endif
static attrib_type at_lighthouse = {
"lighthouse"
/* Rest ist NULL; temporäres, nicht alterndes Attribut */
@ -1031,20 +1017,6 @@ int read_unitid(const faction * f, const region * r)
/* exported symbol */
bool getunitpeasants;
unit *getunitg(const region * r, const faction * f)
{
int n = read_unitid(f, r);
if (n == 0) {
getunitpeasants = 1;
return NULL;
}
getunitpeasants = 0;
if (n < 0)
return 0;
return findunit(n);
}
unit *getunit(const region * r, const faction * f)
{
@ -1632,9 +1604,6 @@ void kernel_done(void)
gc_done();
}
/* TODO: soll hier weg */
extern struct attrib_type at_shiptrail;
attrib_type at_germs = {
"germs",
DEFAULT_INIT,
@ -2168,6 +2137,7 @@ bool has_limited_skills(const struct unit * u)
void attrib_init(void)
{
/* Alle speicherbaren Attribute müssen hier registriert werden */
at_register(&at_speedup);
at_register(&at_shiptrail);
at_register(&at_familiar);
at_register(&at_familiarmage);
@ -2211,7 +2181,6 @@ void attrib_init(void)
at_register(&at_germs);
at_deprecate("xontormiaexpress", a_readint); /* required for old datafiles */
at_register(&at_speedup);
}
void kernel_init(void)
@ -2290,11 +2259,7 @@ void free_gamedata(void)
defaults[i] = 0;
}
}
while (alliances) {
alliance *al = alliances;
alliances = al->next;
free_alliance(al);
}
free_alliances();
while (factions) {
faction *f = factions;
factions = f->next;

View File

@ -34,9 +34,6 @@ extern "C" {
#define INSECT_POTION /* Spezialtrank für Insekten */
#define ORCIFICATION /* giving snotlings to the peasants gets counted */
// TODO: remove macro, move all alliance code into a module.
#define ALLIED(f1, f2) (f1==f2 || (f1->alliance && f1->alliance==f2->alliance))
/* for some good prime numbers, check http://www.math.niu.edu/~rusin/known-math/98/pi_x */
#ifndef MAXREGIONS
# define MAXREGIONS 524287 /* must be prime for hashing. 262139 was a little small */
@ -166,7 +163,6 @@ extern "C" {
struct unit *createunit(struct region *r, struct faction *f,
int number, const struct race *rc);
void create_unitid(struct unit *u, int id);
struct unit *getunitg(const struct region *r, const struct faction *f);
struct unit *getunit(const struct region *r, const struct faction *f);
int read_unitid(const struct faction *f, const struct region *r);

View File

@ -480,9 +480,6 @@ item *i_change(item ** pi, const item_type * itype, int delta)
i->number += delta;
if (i->number < 0) {
log_error("serious accounting error. number of items is %d.\n", i->number);
/* FIXME what's this supposed to mean??
assert(i >= 0);
*/
i->number = 0;
}
if (i->number == 0) {

View File

@ -568,6 +568,7 @@ keyword_t init_order(const struct order *ord)
{
char *cmd = 0;
assert(ord && ord->data);
if (ord->data->_str) cmd = _strdup(ord->data->_str);
init_tokens_str(cmd, cmd);
return ord->data->_keyword;

View File

@ -552,43 +552,6 @@ static int parse_ships(xmlDocPtr doc)
return 0;
}
#if 0
static void race_compat(void)
{
/* required for old_race, do not change order! */
const char *oldracenames[MAXRACES] = {
"dwarf", "elf", NULL, "goblin", "human", "troll", "demon", "insect",
"halfling", "cat", "aquarian", "orc", "snotling", "undead", "illusion",
"youngdragon", "dragon", "wyrm", "ent", "catdragon", "dracoid",
"special", "spell", "irongolem", "stonegolem", "shadowdemon",
"shadowmaster", "mountainguard", "alp", "toad", "braineater", "peasant",
"wolf", NULL, NULL, NULL, NULL, "songdragon", NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, "seaserpent",
"shadowknight", "centaur", "skeleton", "skeletonlord", "zombie",
"juju-zombie", "ghoul", "ghast", "museumghost", "gnome", "template",
"clone"
};
int i;
for (i = 0; i != MAXRACES; ++i) {
const char *rcname = oldracenames[i];
if (rcname == NULL) {
new_race[i] = NULL;
} else {
race *rc = rc_get_or_create(oldracenames[i]);
if (rc) {
new_race[i] = rc;
if (rc == new_race[RC_TROLL]) {
a_add(&rc->attribs, make_skillmod(NOSKILL, SMF_RIDING, NULL, 0.0,
-1));
}
}
}
}
}
#endif
static potion_type *xml_readpotion(xmlXPathContextPtr xpath, item_type * itype)
{
int level = xml_ivalue(xpath->node, "level", 0);

View File

@ -28,6 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "economy.h"
#include "keyword.h"
#include "market.h"
#include "morale.h"
#include "monster.h"
#include "move.h"
#include "randenc.h"
@ -857,19 +858,15 @@ int can_contact(const region * r, const unit * u, const unit * u2) {
int contact_cmd(unit * u, order * ord)
{
/* unit u kontaktiert unit u2. Dies setzt den contact einfach auf 1 -
* ein richtiger toggle ist (noch?) nicht noetig. die region als
* parameter ist nur deswegen wichtig, weil er an getunit ()
* weitergegeben wird. dies wird fuer das auffinden von tempunits in
* getnewunit () verwendet! */
unit *u2;
region *r = u->region;
int n;
init_order(ord);
u2 = getunitg(r, u->faction);
n = read_unitid(u->faction, u->region);
u2 = findunit(n);
if (u2 != NULL) {
if (!can_contact(r, u, u2)) {
if (!can_contact(u->region, u, u2)) {
cmistake(u, u->thisorder, 23, MSG_EVENT);
return -1;
}
@ -3160,12 +3157,6 @@ static building *age_building(building * b)
return b;
}
static double rc_popularity(const struct race *rc)
{
int pop = get_param_int(rc->parameters, "morale", MORALE_AVERAGE);
return 1.0 / (pop - MORALE_COOLDOWN); /* 10 turns average */
}
static void age_region(region * r)
{
a_age(&r->attribs);
@ -3174,33 +3165,7 @@ static void age_region(region * r)
if (!r->land)
return;
if (r->land->ownership && r->land->ownership->owner) {
int stability = turn - r->land->ownership->morale_turn;
int maxmorale = MORALE_DEFAULT;
building *b = largestbuilding(r, &cmp_taxes, false);
if (b) {
int bsize = buildingeffsize(b, false);
maxmorale = (int)(0.5 + b->type->taxes(b, bsize + 1) / MORALE_TAX_FACTOR);
}
if (r->land->morale < maxmorale) {
if (stability > MORALE_COOLDOWN && r->land->ownership->owner
&& r->land->morale < MORALE_MAX) {
double ch = rc_popularity(r->land->ownership->owner->race);
if (is_cursed(r->attribs, C_GENEROUS, 0)) {
ch *= 1.2; /* 20% improvement */
}
if (stability >= MORALE_AVERAGE * 2 || chance(ch)) {
region_set_morale(r, r->land->morale + 1, turn);
}
}
}
else if (r->land->morale > maxmorale) {
region_set_morale(r, r->land->morale - 1, turn);
}
}
else if (r->land->morale > MORALE_DEFAULT) {
region_set_morale(r, r->land->morale - 1, turn);
}
morale_update(r);
}
static void ageing(void)

74
src/morale.c Normal file
View File

@ -0,0 +1,74 @@
/*
Copyright (c) 1998-2014,
Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
#include <platform.h>
#include "morale.h"
#include <kernel/config.h>
#include <kernel/curse.h>
#include <kernel/region.h>
#include <kernel/faction.h>
#include <kernel/race.h>
#include <kernel/building.h>
#include <util/rand.h>
static double rc_popularity(const struct race *rc)
{
int pop = get_param_int(rc->parameters, "morale", MORALE_AVERAGE);
return 1.0 / (pop - MORALE_COOLDOWN); /* 10 turns average */
}
void morale_update(region *r) {
if (r->land->ownership && r->land->ownership->owner) {
int stability = turn - r->land->ownership->morale_turn;
int maxmorale = MORALE_DEFAULT;
building *b = largestbuilding(r, &cmp_taxes, false);
if (b) {
int bsize = buildingeffsize(b, false);
maxmorale = (int)(0.5 + b->type->taxes(b, bsize + 1) / MORALE_TAX_FACTOR);
}
if (r->land->morale < maxmorale) {
if (stability > MORALE_COOLDOWN && r->land->ownership->owner
&& r->land->morale < MORALE_MAX) {
double ch = rc_popularity(r->land->ownership->owner->race);
if (is_cursed(r->attribs, C_GENEROUS, 0)) {
ch *= 1.2; /* 20% improvement */
}
if (stability >= MORALE_AVERAGE * 2 || chance(ch)) {
region_set_morale(r, r->land->morale + 1, turn);
}
}
}
else if (r->land->morale > maxmorale) {
region_set_morale(r, r->land->morale - 1, turn);
}
}
else if (r->land->morale > MORALE_DEFAULT) {
region_set_morale(r, r->land->morale - 1, turn);
}
}
void morale_change(region *r, int value) {
int morale = region_get_morale(r);
if (morale > 0) {
morale = _max(0, morale - value);
region_set_morale(r, morale, turn);
}
}

View File

@ -16,13 +16,18 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
#ifndef H_ATTRIBUTE_ALLIANCE
#define H_ATTRIBUTE_ALLIANCE
#ifndef H_GC_MORALE
#define H_GC_MORALE
#include <kernel/types.h>
#ifdef __cplusplus
extern "C" {
#endif
extern struct attrib_type at_alliance;
struct region;
void morale_update(struct region *r);
void morale_change(struct region *r, int value);
#ifdef __cplusplus
}

View File

@ -32,6 +32,7 @@ extern "C" {
struct building_type;
extern struct attrib_type at_speedup;
extern struct attrib_type at_shiptrail;
/* die Zahlen sind genau äquivalent zu den race Flags */
#define MV_CANNOTMOVE (1<<5)

View File

@ -31,7 +31,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* attributes includes */
#include <attributes/overrideroads.h>
#include <attributes/otherfaction.h>
#include <attributes/alliance.h>
#include <attributes/reduceproduction.h>
/* gamecode includes */
@ -711,8 +710,7 @@ nr_unit(FILE * F, const faction * f, const unit * u, int indent, int mode)
if (u->faction == f) {
marker = '*';
}
else if ALLIED
(u->faction, f) {
else if (is_allied(u->faction, f)) {
marker = 'o';
}
else if (a_otherfaction && f != u->faction
@ -1889,7 +1887,7 @@ static void list_address(FILE * F, const faction * uf, quicklist * seenfactions)
f->banner ? f->banner : "");
if (uf == f)
label = '*';
else if (ALLIED(uf, f))
else if (is_allied(uf, f))
label = 'o';
else if (alliedfaction(NULL, uf, f, HELP_ALL))
label = '+';
@ -2046,62 +2044,12 @@ const faction * f)
WARN_STATIC_BUFFER();
i = b->display[strlen(b->display) - 1];
}
#ifdef WDW_PYRAMID
if (i != '!' && i != '?' && i != '.') {
scat(", ");
}
if (b->type == bt_find("pyramid")) {
unit *owner = building_owner(b);
scat("Größenstufe ");
icat(wdw_pyramid_level(b));
scat(".");
if (owner && owner->faction == f) {
const construction *ctype = b->type->construction;
int completed = b->size;
int c;
scat(" Baukosten pro Größenpunkt: ");
while (ctype->improvement != NULL &&
ctype->improvement != ctype &&
ctype->maxsize > 0 && ctype->maxsize <= completed) {
completed -= ctype->maxsize;
ctype = ctype->improvement;
}
assert(ctype->materials != NULL);
for (c = 0; ctype->materials[c].number; c++) {
const resource_type *rtype = ctype->materials[c].rtype;
int number = ctype->materials[c].number;
if (c > 0) {
scat(", ");
}
icat(number);
scat(" ");
scat(locale_string(lang, resourcename(rtype,
number != 1 ? GR_PLURAL : 0)));
}
scat(".");
scat(" Erforderlicher Talentwert: ");
icat(b->type->construction->minskill);
scat(".");
}
}
#else
if (i != '!' && i != '?' && i != '.') {
bytes = (int)strlcpy(bufp, ".", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
}
#endif
*bufp = 0;
rparagraph(F, buffer, 2, 0, 0);

View File

@ -1108,7 +1108,7 @@ static void get_addresses(report_context * ctx)
faction *sf = visible_faction(ctx->f, u);
bool ballied = sf && sf != ctx->f && sf != lastf
&& !fval(u, UFL_ANON_FACTION) && cansee(ctx->f, r, u, stealthmod);
if (ballied || ALLIED(ctx->f, sf)) {
if (ballied || is_allied(ctx->f, sf)) {
add_seen_faction_i(&flist, sf);
lastf = sf;
}

View File

@ -394,46 +394,10 @@ int report_action(region * r, unit * actor, message * msg, int flags)
static void
report_effect(region * r, unit * mage, message * seen, message * unseen)
{
#if 0
unit *u;
/* melden, 1x pro Partei */
freset(mage->faction, FFL_SELECT);
for (u = r->units; u; u = u->next)
freset(u->faction, FFL_SELECT);
for (u = r->units; u; u = u->next) {
if (!fval(u->faction, FFL_SELECT)) {
fset(u->faction, FFL_SELECT);
/* Bei Fernzaubern sieht nur die eigene Partei den Magier */
if (u->faction != mage->faction) {
if (r == mage->region) {
/* kein Fernzauber, pruefe, ob der Magier ueberhaupt gesehen
* wird */
if (cansee(u->faction, r, mage, 0)) {
r_addmessage(r, u->faction, seen);
} else {
r_addmessage(r, u->faction, unseen);
}
} else { /* Fernzauber, fremde Partei sieht den Magier niemals */
r_addmessage(r, u->faction, unseen);
}
} else { /* Partei des Magiers, sieht diesen immer */
r_addmessage(r, u->faction, seen);
}
}
}
/* Ist niemand von der Partei des Magiers in der Region, dem Magier
* nochmal gesondert melden */
if (!fval(mage->faction, FFL_SELECT)) {
add_message(&mage->faction->msgs, seen);
}
#else
int err = report_action(r, mage, seen, ACTION_RESET | ACTION_CANSEE);
if (err) {
report_action(r, mage, seen, ACTION_CANNOTSEE);
}
#endif
}
/* ------------------------------------------------------------- */
@ -3613,11 +3577,6 @@ static int sp_charmingsong(castorder * co)
/* Magieresistenz */
if (target_resists_magic(mage, target, TYP_UNIT, resist_bonus)) {
report_failure(mage, co->order);
#if 0
sprintf(buf, "%s fuehlt sich einen Moment lang benommen und desorientiert.",
unitname(target));
addmessage(target->region, target->faction, buf, MSG_EVENT, ML_WARN);
#endif
return 0;
}
@ -6526,54 +6485,6 @@ int sp_becomewyrm(castorder * co)
return 0;
}
/* ------------------------------------------------------------- */
/* Name: WDW-Pyramidenfindezauber
* Stufe: unterschiedlich
* Gebiet: alle
* Wirkung:
* gibt die ungefaehre Entfernung zur naechstgelegenen Pyramiden-
* region an.
*
* Flags:
*/
static int sp_wdwpyramid(castorder * co)
{
region *r = co_get_region(co);
unit *mage = co->magician.u;
int cast_level = co->level;
if (a_find(r->attribs, &at_wdwpyramid) != NULL) {
ADDMSG(&mage->faction->msgs, msg_message("wdw_pyramidspell_found",
"unit region command", mage, r, co->order));
}
else {
region *r2;
int mindist = INT_MAX;
int minshowdist;
int maxshowdist;
for (r2 = regions; r2; r2 = r2->next) {
if (a_find(r2->attribs, &at_wdwpyramid) != NULL) {
int dist = distance(mage->region, r2);
if (dist < mindist) {
mindist = dist;
}
}
}
assert(mindist >= 1);
minshowdist = mindist - rng_int() % 5;
maxshowdist = minshowdist + 4;
ADDMSG(&mage->faction->msgs, msg_message("wdw_pyramidspell_notfound",
"unit region command mindist maxdist", mage, r, co->order,
_max(1, minshowdist), maxshowdist));
}
return cast_level;
}
typedef struct spelldata {
const char *sname;
spell_f cast;
@ -6861,7 +6772,6 @@ void register_spells(void)
ct_register(&ct_deathcloud);
register_function((pf_generic)sp_blessedharvest, "cast_blessedharvest");
register_function((pf_generic)sp_wdwpyramid, "wdwpyramid");
register_function((pf_generic)sp_summon_familiar, "cast_familiar");
register_function((pf_generic)sp_babbler, "cast_babbler");
register_function((pf_generic)sp_readmind, "cast_readmind");

View File

@ -38,6 +38,7 @@ int RunAllTests(void)
ADD_TESTS(suite, unicode);
ADD_TESTS(suite, strings);
/* kernel */
ADD_TESTS(suite, alliance);
ADD_TESTS(suite, unit);
ADD_TESTS(suite, faction);
ADD_TESTS(suite, group);

View File

@ -23,7 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* kernel includes */
#include <kernel/unit.h>
#include <kernel/save.h>
#include <kernel/faction.h> /* FIXME: resolve_faction */
#include <kernel/faction.h>
/* util includes */
#include <util/attrib.h>