Merge pull request #412 from ennorehling/develop

cleaning up config.c some more
This commit is contained in:
Enno Rehling 2015-11-25 12:11:30 +01:00
commit 41a6265a80
26 changed files with 601 additions and 553 deletions

View File

@ -20,12 +20,17 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <kernel/config.h>
#include "attributes.h"
#include "laws.h"
#include "move.h"
#include "guard.h"
/* attributes includes */
#include "follow.h"
#include "hate.h"
#include "iceberg.h"
#include "key.h"
#include "stealth.h"
#include "magic.h"
#include "moved.h"
#include "movement.h"
#include "dict.h"
@ -38,8 +43,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "targetregion.h"
/* kernel includes */
#include <kernel/ally.h>
#include <kernel/connection.h>
#include <kernel/curse.h>
#include <kernel/unit.h>
#include <kernel/faction.h>
#include <kernel/group.h>
#include <kernel/region.h>
#include <kernel/save.h>
#include <kernel/ship.h>
@ -47,13 +56,67 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */
#include <util/attrib.h>
#include <util/event.h>
#include <storage.h>
attrib_type at_unitdissolve = {
"unitdissolve", NULL, NULL, NULL, a_writechars, a_readchars
};
static int read_ext(attrib * a, void *owner, struct storage *store)
{
int len;
READ_INT(store, &len);
store->api->r_bin(store->handle, NULL, (size_t)len);
return AT_READ_OK;
}
void register_attributes(void)
{
/* Alle speicherbaren Attribute müssen hier registriert werden */
at_register(&at_shiptrail);
at_register(&at_familiar);
at_register(&at_familiarmage);
at_register(&at_clone);
at_register(&at_clonemage);
at_register(&at_eventhandler);
at_register(&at_mage);
at_register(&at_countdown);
at_register(&at_curse);
at_register(&at_seenspell);
/* neue REGION-Attribute */
at_register(&at_moveblock);
at_register(&at_deathcount);
at_register(&at_woodcount);
/* neue UNIT-Attribute */
at_register(&at_siege);
at_register(&at_effect);
at_register(&at_private);
at_register(&at_icastle);
at_register(&at_guard);
at_register(&at_group);
at_register(&at_building_generic_type);
at_register(&at_maxmagicians);
at_register(&at_npcfaction);
/* connection-typen */
register_bordertype(&bt_noway);
register_bordertype(&bt_fogwall);
register_bordertype(&bt_wall);
register_bordertype(&bt_illusionwall);
register_bordertype(&bt_road);
at_register(&at_germs);
at_deprecate("xontormiaexpress", a_readint); /* required for old datafiles */
at_deprecate("lua", read_ext); /* required for old datafiles */
at_deprecate("gm", a_readint);
at_register(&at_stealth);
at_register(&at_dict);

View File

@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <kernel/config.h>
#include "otherfaction.h"
#include <kernel/ally.h>
#include <kernel/faction.h>
#include <kernel/unit.h>
#include <util/attrib.h>

View File

@ -27,6 +27,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "skill.h"
#include "monster.h"
#include <kernel/ally.h>
#include <kernel/alliance.h>
#include <kernel/build.h>
#include <kernel/building.h>

View File

@ -35,6 +35,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "calendar.h"
/* kernel includes */
#include <kernel/ally.h>
#include <kernel/building.h>
#include <kernel/curse.h>
#include <kernel/equipment.h>

View File

@ -18,6 +18,7 @@
#include "laws.h"
/* kernel includes */
#include <kernel/ally.h>
#include <kernel/curse.h>
#include <kernel/faction.h>
#include <kernel/item.h>
@ -208,6 +209,17 @@ struct order *ord)
return 0;
}
static bool unit_has_cursed_item(const unit * u)
{
item *itm = u->items;
while (itm) {
if (fval(itm->type, ITF_CURSED) && itm->number > 0)
return true;
itm = itm->next;
}
return false;
}
static bool can_give_men(const unit *u, order *ord, message **msg) {
if (u_race(u) == get_race(RC_SNOTLING)) {
/* snotlings may not be given to the peasants. */

View File

@ -1,6 +1,18 @@
#include "platform.h"
#include "config.h"
#include "types.h"
#include "ally.h"
#include "save.h"
#include "unit.h"
#include "region.h"
#include "group.h"
#include "faction.h"
#include "plane.h"
#include <util/attrib.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
ally * ally_find(ally *al, const struct faction *f) {
@ -37,3 +49,192 @@ void ally_remove(ally **al_p, struct faction *f) {
al_p = &al->next;
}
}
static int ally_flag(const char *s, int help_mask)
{
if ((help_mask & HELP_MONEY) && strcmp(s, "money") == 0)
return HELP_MONEY;
if ((help_mask & HELP_FIGHT) && strcmp(s, "fight") == 0)
return HELP_FIGHT;
if ((help_mask & HELP_GIVE) && strcmp(s, "give") == 0)
return HELP_GIVE;
if ((help_mask & HELP_GUARD) && strcmp(s, "guard") == 0)
return HELP_GUARD;
if ((help_mask & HELP_FSTEALTH) && strcmp(s, "stealth") == 0)
return HELP_FSTEALTH;
if ((help_mask & HELP_TRAVEL) && strcmp(s, "travel") == 0)
return HELP_TRAVEL;
return 0;
}
/** Specifies automatic alliance modes.
* If this returns a value then the bits set are immutable between alliance
* partners (faction::alliance) and cannot be changed with the HELP command.
*/
int AllianceAuto(void)
{
int value;
const char *str = config_get("alliance.auto");
value = 0;
if (str != NULL) {
char *sstr = _strdup(str);
char *tok = strtok(sstr, " ");
while (tok) {
value |= ally_flag(tok, -1);
tok = strtok(NULL, " ");
}
free(sstr);
}
return value & HelpMask();
}
static int
autoalliance(const plane * pl, const faction * sf, const faction * f2)
{
if (pl && (pl->flags & PFL_FRIENDLY))
return HELP_ALL;
if (f_get_alliance(sf) != NULL && AllianceAuto()) {
if (sf->alliance == f2->alliance)
return AllianceAuto();
}
return 0;
}
static int ally_mode(const ally * sf, int mode)
{
if (sf == NULL)
return 0;
return sf->status & mode;
}
static void init_npcfaction(struct attrib *a)
{
a->data.i = 1;
}
attrib_type at_npcfaction = {
"npcfaction",
init_npcfaction,
NULL,
NULL,
a_writeint,
a_readint,
ATF_UNIQUE
};
/** Limits the available help modes
* The bitfield returned by this function specifies the available help modes
* in this game (so you can, for example, disable HELP GIVE globally).
* Disabling a status will disable the command sequence entirely (order parsing
* uses this function).
*/
int HelpMask(void)
{
const char *str = config_get("rules.help.mask");
int rule = 0;
if (str != NULL) {
char *sstr = _strdup(str);
char *tok = strtok(sstr, " ");
while (tok) {
rule |= ally_flag(tok, -1);
tok = strtok(NULL, " ");
}
free(sstr);
}
else {
rule = HELP_ALL;
}
return rule;
}
static int AllianceRestricted(void)
{
const char *str = config_get("alliance.restricted");
int rule = 0;
if (str != NULL) {
char *sstr = _strdup(str);
char *tok = strtok(sstr, " ");
while (tok) {
rule |= ally_flag(tok, -1);
tok = strtok(NULL, " ");
}
free(sstr);
}
rule &= HelpMask();
return rule;
}
int
alliedgroup(const struct plane *pl, const struct faction *f,
const struct faction *f2, const struct ally *sf, int mode)
{
while (sf && sf->faction != f2)
sf = sf->next;
if (sf == NULL) {
mode = mode & autoalliance(pl, f, f2);
}
mode = ally_mode(sf, mode) | (mode & autoalliance(pl, f, f2));
if (AllianceRestricted()) {
if (a_findc(f->attribs, &at_npcfaction)) {
return mode;
}
if (a_findc(f2->attribs, &at_npcfaction)) {
return mode;
}
if (f->alliance != f2->alliance) {
mode &= ~AllianceRestricted();
}
}
return mode;
}
int
alliedfaction(const struct plane *pl, const struct faction *f,
const struct faction *f2, int mode)
{
return alliedgroup(pl, f, f2, f->allies, mode);
}
/* Die Gruppe von Einheit u hat helfe zu f2 gesetzt. */
int alliedunit(const unit * u, const faction * f2, int mode)
{
ally *sf;
int automode;
assert(u);
assert(f2);
assert(u->region); /* the unit should be in a region, but it's possible that u->number==0 (TEMP units) */
if (u->faction == f2)
return mode;
if (u->faction != NULL && f2 != NULL) {
plane *pl;
if (mode & HELP_FIGHT) {
if ((u->flags & UFL_DEFENDER) || (u->faction->flags & FFL_DEFENDER)) {
faction *owner = region_get_owner(u->region);
/* helps the owner of the region */
if (owner == f2) {
return HELP_FIGHT;
}
}
}
pl = rplane(u->region);
automode = mode & autoalliance(pl, u->faction, f2);
if (pl != NULL && (pl->flags & PFL_NOALLIANCES))
mode = (mode & automode) | (mode & HELP_GIVE);
sf = u->faction->allies;
if (fval(u, UFL_GROUP)) {
const attrib *a = a_findc(u->attribs, &at_group);
if (a != NULL)
sf = ((group *)a->data.v)->allies;
}
return alliedgroup(pl, u->faction, f2, sf, mode);
}
return 0;
}

View File

@ -23,6 +23,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
extern "C" {
#endif
struct attrib_type;
struct plane;
struct faction;
struct unit;
extern struct attrib_type at_npcfaction;
typedef struct ally {
struct ally *next;
struct faction *faction;
@ -33,6 +39,15 @@ extern "C" {
ally * ally_add(ally **al_p, struct faction *f);
void ally_remove(ally **al_p, struct faction *f);
int AllianceAuto(void); /* flags that allied factions get automatically */
int HelpMask(void); /* flags restricted to allied factions */
int alliedunit(const struct unit *u, const struct faction *f2,
int mode);
int alliedfaction(const struct plane *pl, const struct faction *f,
const struct faction *f2, int mode);
int alliedgroup(const struct plane *pl, const struct faction *f,
const struct faction *f2, const struct ally *sf, int mode);
#ifdef __cplusplus
}
#endif

View File

@ -28,6 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "lighthouse.h"
/* kernel includes */
#include <kernel/ally.h>
#include <kernel/alliance.h>
#include <kernel/connection.h>
#include <kernel/building.h>

View File

@ -44,7 +44,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "race.h"
#include "reports.h"
#include "region.h"
#include "save.h"
#include "ship.h"
#include "skill.h"
#include "terrain.h"
@ -85,7 +84,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#endif
/* external libraries */
#include <storage.h>
#include <iniparser.h>
#include <critbit.h>
@ -117,91 +115,11 @@ bool IsImmune(const faction * f)
return !fval(f, FFL_NPC) && f->age < NewbieImmunity();
}
static int ally_flag(const char *s, int help_mask)
{
if ((help_mask & HELP_MONEY) && strcmp(s, "money") == 0)
return HELP_MONEY;
if ((help_mask & HELP_FIGHT) && strcmp(s, "fight") == 0)
return HELP_FIGHT;
if ((help_mask & HELP_GIVE) && strcmp(s, "give") == 0)
return HELP_GIVE;
if ((help_mask & HELP_GUARD) && strcmp(s, "guard") == 0)
return HELP_GUARD;
if ((help_mask & HELP_FSTEALTH) && strcmp(s, "stealth") == 0)
return HELP_FSTEALTH;
if ((help_mask & HELP_TRAVEL) && strcmp(s, "travel") == 0)
return HELP_TRAVEL;
return 0;
}
bool ExpensiveMigrants(void)
{
return config_get_int("study.expensivemigrants", 0) != 0;
}
/** Specifies automatic alliance modes.
* If this returns a value then the bits set are immutable between alliance
* partners (faction::alliance) and cannot be changed with the HELP command.
*/
int AllianceAuto(void)
{
int value;
const char *str = config_get("alliance.auto");
value = 0;
if (str != NULL) {
char *sstr = _strdup(str);
char *tok = strtok(sstr, " ");
while (tok) {
value |= ally_flag(tok, -1);
tok = strtok(NULL, " ");
}
free(sstr);
}
return value & HelpMask();
}
/** Limits the available help modes
* The bitfield returned by this function specifies the available help modes
* in this game (so you can, for example, disable HELP GIVE globally).
* Disabling a status will disable the command sequence entirely (order parsing
* uses this function).
*/
int HelpMask(void)
{
const char *str = config_get("rules.help.mask");
int rule = 0;
if (str != NULL) {
char *sstr = _strdup(str);
char *tok = strtok(sstr, " ");
while (tok) {
rule |= ally_flag(tok, -1);
tok = strtok(NULL, " ");
}
free(sstr);
}
else {
rule = HELP_ALL;
}
return rule;
}
int AllianceRestricted(void)
{
const char *str = config_get("alliance.restricted");
int rule = 0;
if (str != NULL) {
char *sstr = _strdup(str);
char *tok = strtok(sstr, " ");
while (tok) {
rule |= ally_flag(tok, -1);
tok = strtok(NULL, " ");
}
free(sstr);
}
rule &= HelpMask();
return rule;
}
int LongHunger(const struct unit *u)
{
if (u != NULL) {
@ -247,22 +165,6 @@ helpmode helpmodes[] = {
{ NULL, 0 }
};
/** Returns the English name of the race, which is what the database uses.
*/
const char *dbrace(const struct race *rc)
{
static char zText[32]; // FIXME: static return value
char *zPtr = zText;
/* the english names are all in ASCII, so we don't need to worry about UTF8 */
strlcpy(zText, (const char *)LOC(get_locale("en"), rc_name_s(rc, NAME_SINGULAR)), sizeof(zText));
while (*zPtr) {
*zPtr = (char)(toupper(*zPtr));
++zPtr;
}
return zText;
}
const char *parameters[MAXPARAMS] = {
"LOCALE",
"ALLES",
@ -347,173 +249,8 @@ const char *options[MAXOPTIONS] = {
"SHOWSKCHANGE"
};
static void init_maxmagicians(struct attrib *a)
{
a->data.i = MAXMAGICIANS;
}
static attrib_type at_maxmagicians = {
"maxmagicians",
init_maxmagicians,
NULL,
NULL,
a_writeint,
a_readint,
ATF_UNIQUE
};
int max_magicians(const faction * f)
{
int m = config_get_int("rules.maxskills.magic", MAXMAGICIANS);
attrib *a;
if ((a = a_find(f->attribs, &at_maxmagicians)) != NULL) {
m = a->data.i;
}
if (f->race == get_race(RC_ELF))
++m;
return m;
}
static void init_npcfaction(struct attrib *a)
{
a->data.i = 1;
}
static attrib_type at_npcfaction = {
"npcfaction",
init_npcfaction,
NULL,
NULL,
a_writeint,
a_readint,
ATF_UNIQUE
};
FILE *debug;
/* ----------------------------------------------------------------------- */
int distribute(int old, int new_value, int n)
{
int i;
int t;
assert(new_value <= old);
if (old == 0)
return 0;
t = (n / old) * new_value;
for (i = (n % old); i; i--)
if (rng_int() % old < new_value)
t++;
return t;
}
bool unit_has_cursed_item(const unit * u)
{
item *itm = u->items;
while (itm) {
if (fval(itm->type, ITF_CURSED) && itm->number > 0)
return true;
itm = itm->next;
}
return false;
}
static int
autoalliance(const plane * pl, const faction * sf, const faction * f2)
{
if (pl && (pl->flags & PFL_FRIENDLY))
return HELP_ALL;
if (f_get_alliance(sf) != NULL && AllianceAuto()) {
if (sf->alliance == f2->alliance)
return AllianceAuto();
}
return 0;
}
static int ally_mode(const ally * sf, int mode)
{
if (sf == NULL)
return 0;
return sf->status & mode;
}
int
alliedgroup(const struct plane *pl, const struct faction *f,
const struct faction *f2, const struct ally *sf, int mode)
{
while (sf && sf->faction != f2)
sf = sf->next;
if (sf == NULL) {
mode = mode & autoalliance(pl, f, f2);
}
mode = ally_mode(sf, mode) | (mode & autoalliance(pl, f, f2));
if (AllianceRestricted()) {
if (a_findc(f->attribs, &at_npcfaction)) {
return mode;
}
if (a_findc(f2->attribs, &at_npcfaction)) {
return mode;
}
if (f->alliance != f2->alliance) {
mode &= ~AllianceRestricted();
}
}
return mode;
}
int
alliedfaction(const struct plane *pl, const struct faction *f,
const struct faction *f2, int mode)
{
return alliedgroup(pl, f, f2, f->allies, mode);
}
/* Die Gruppe von Einheit u hat helfe zu f2 gesetzt. */
int alliedunit(const unit * u, const faction * f2, int mode)
{
ally *sf;
int automode;
assert(u);
assert(f2);
assert(u->region); /* the unit should be in a region, but it's possible that u->number==0 (TEMP units) */
if (u->faction == f2)
return mode;
if (u->faction != NULL && f2 != NULL) {
plane *pl;
if (mode & HELP_FIGHT) {
if ((u->flags & UFL_DEFENDER) || (u->faction->flags & FFL_DEFENDER)) {
faction *owner = region_get_owner(u->region);
/* helps the owner of the region */
if (owner == f2) {
return HELP_FIGHT;
}
}
}
pl = rplane(u->region);
automode = mode & autoalliance(pl, u->faction, f2);
if (pl != NULL && (pl->flags & PFL_NOALLIANCES))
mode = (mode & automode) | (mode & HELP_GIVE);
sf = u->faction->allies;
if (fval(u, UFL_GROUP)) {
const attrib *a = a_findc(u->attribs, &at_group);
if (a != NULL)
sf = ((group *)a->data.v)->allies;
}
return alliedgroup(pl, u->faction, f2, sf, mode);
}
return 0;
}
void
parse(keyword_t kword, int(*dofun) (unit *, struct order *), bool thisorder)
{
@ -619,11 +356,6 @@ param_t getparam(const struct locale * lang)
return s ? findparam(s, lang) : NOPARAM;
}
faction *getfaction(void)
{
return findfaction(getid());
}
unit *getnewunit(const region * r, const faction * f)
{
int n;
@ -632,67 +364,6 @@ unit *getnewunit(const region * r, const faction * f)
return findnewunit(r, f, n);
}
static int read_newunitid(const faction * f, const region * r)
{
int n;
unit *u2;
n = getid();
if (n == 0)
return -1;
u2 = findnewunit(r, f, n);
if (u2)
return u2->no;
return -1;
}
int read_unitid(const faction * f, const region * r)
{
char token[16];
const char *s = gettoken(token, sizeof(token));
/* Da s nun nur einen string enthaelt, suchen wir ihn direkt in der
* paramliste. machen wir das nicht, dann wird getnewunit in s nach der
* nummer suchen, doch dort steht bei temp-units nur "temp" drinnen! */
if (!s || *s == 0 || !isalnum(*s)) {
return -1;
}
if (isparam(s, f->locale, P_TEMP)) {
return read_newunitid(f, r);
}
return atoi36((const char *)s);
}
int getunit(const region * r, const faction * f, unit **uresult)
{
unit *u2 = NULL;
int n = read_unitid(f, r);
int result = GET_NOTFOUND;
if (n == 0) {
result = GET_PEASANTS;
}
else if (n > 0) {
u2 = findunit(n);
if (u2 != NULL && u2->region == r) {
/* there used to be a 'u2->flags & UFL_ISNEW || u2->number>0' condition
* here, but it got removed because of a bug that made units disappear:
* http://eressea.upb.de/mantis/bug_view_page.php?bug_id=0000172
*/
result = GET_UNIT;
}
else {
u2 = NULL;
}
}
if (uresult) {
*uresult = u2;
}
return result;
}
/* - Namen der Strukturen -------------------------------------- */
char *untilde(char *ibuf)
{
@ -727,8 +398,6 @@ building *largestbuilding(const region * r, cmp_building_cb cmp_gt,
/* -- Erschaffung neuer Einheiten ------------------------------ */
extern faction *dfindhash(int i);
static const char *forbidden[] = { "t", "te", "tem", "temp", NULL };
// PEASANT: "b", "ba", "bau", "baue", "p", "pe", "pea", "peas"
@ -753,28 +422,6 @@ int forbiddenid(int id)
return 0;
}
/* ID's für Einheiten und Zauber */
int newunitid(void)
{
int random_unit_no;
int start_random_no;
random_unit_no = 1 + (rng_int() % MAX_UNIT_NR);
start_random_no = random_unit_no;
while (ufindhash(random_unit_no) || dfindhash(random_unit_no)
|| cfindhash(random_unit_no)
|| forbiddenid(random_unit_no)) {
random_unit_no++;
if (random_unit_no == MAX_UNIT_NR + 1) {
random_unit_no = 1;
}
if (random_unit_no == start_random_no) {
random_unit_no = (int)MAX_UNIT_NR + 1;
}
}
return random_unit_no;
}
int newcontainerid(void)
{
int random_no;
@ -1055,24 +702,6 @@ void kernel_done(void)
free_attribs();
}
attrib_type at_germs = {
"germs",
DEFAULT_INIT,
DEFAULT_FINALIZE,
DEFAULT_AGE,
a_writeshorts,
a_readshorts,
ATF_UNIQUE
};
void setstatus(struct unit *u, int status)
{
assert(status >= ST_AGGRO && status <= ST_FLEE);
if (u->status != status) {
u->status = (status_t)status;
}
}
#ifndef HAVE_STRDUP
char *_strdup(const char *s)
{
@ -1080,24 +709,6 @@ char *_strdup(const char *s)
}
#endif
int besieged(const unit * u)
{
/* belagert kann man in schiffen und burgen werden */
return (u && !keyword_disabled(K_BESIEGE)
&& u->building && u->building->besieged
&& u->building->besieged >= u->building->size * SIEGEFACTOR);
}
bool has_horses(const struct unit * u)
{
item *itm = u->items;
for (; itm; itm = itm->next) {
if (itm->type->flags & ITF_ANIMAL)
return true;
}
return false;
}
/* Lohn bei den einzelnen Burgstufen für Normale Typen, Orks, Bauern,
* Modifikation für Städter. */
@ -1335,19 +946,6 @@ int wage(const region * r, const faction * f, const race * rc, int in_turn)
return default_wage(r, f, rc, in_turn);
}
#define MAINTENANCE 10
int maintenance_cost(const struct unit *u)
{
if (u == NULL)
return MAINTENANCE;
if (global.functions.maintenance) {
int retval = global.functions.maintenance(u);
if (retval >= 0)
return retval;
}
return u_race(u)->maintenance * u->number;
}
int lovar(double xpct_x2)
{
int n = (int)(xpct_x2 * 500) + 1;
@ -1356,82 +954,12 @@ int lovar(double xpct_x2)
return (rng_int() % n + rng_int() % n) / 1000;
}
bool has_limited_skills(const struct unit * u)
{
if (has_skill(u, SK_MAGIC) || has_skill(u, SK_ALCHEMY) ||
has_skill(u, SK_TACTICS) || has_skill(u, SK_HERBALISM) ||
has_skill(u, SK_SPY)) {
return true;
}
else {
return false;
}
}
static int read_ext(attrib * a, void *owner, struct storage *store)
{
int len;
READ_INT(store, &len);
store->api->r_bin(store->handle, NULL, (size_t)len);
return AT_READ_OK;
}
void attrib_init(void)
{
/* Alle speicherbaren Attribute müssen hier registriert werden */
at_register(&at_shiptrail);
at_register(&at_familiar);
at_register(&at_familiarmage);
at_register(&at_clone);
at_register(&at_clonemage);
at_register(&at_eventhandler);
at_register(&at_mage);
at_register(&at_countdown);
at_register(&at_curse);
at_register(&at_seenspell);
/* neue REGION-Attribute */
at_register(&at_moveblock);
at_register(&at_deathcount);
at_register(&at_woodcount);
/* neue UNIT-Attribute */
at_register(&at_siege);
at_register(&at_effect);
at_register(&at_private);
at_register(&at_icastle);
at_register(&at_guard);
at_register(&at_group);
at_register(&at_building_generic_type);
at_register(&at_maxmagicians);
at_register(&at_npcfaction);
/* connection-typen */
register_bordertype(&bt_noway);
register_bordertype(&bt_fogwall);
register_bordertype(&bt_wall);
register_bordertype(&bt_illusionwall);
register_bordertype(&bt_road);
register_function((pf_generic)minimum_wage, "minimum_wage");
at_register(&at_germs);
at_deprecate("xontormiaexpress", a_readint); /* required for old datafiles */
at_deprecate("lua", read_ext); /* required for old datafiles */
}
void kernel_init(void)
{
register_reports();
mt_clear();
attrib_init();
translation_init();
register_function((pf_generic)minimum_wage, "minimum_wage");
}
static order * defaults[MAXLOCALES];

View File

@ -27,11 +27,6 @@ extern "C" {
#include "types.h"
struct param;
/* getunit results: */
#define GET_UNIT 0
#define GET_NOTFOUND 1
#define GET_PEASANTS 2
#define DISPLAYSIZE 8192 /* max. Länge einer Beschreibung, incl trailing 0 */
#define ORDERSIZE (DISPLAYSIZE*2) /* max. length of an order */
#define NAMESIZE 128 /* max. Länge eines Namens, incl trailing 0 */
@ -50,7 +45,6 @@ struct param;
#define fset(u, i) ((u)->flags |= (i))
#define freset(u, i) ((u)->flags &= ~(i))
int max_magicians(const struct faction * f);
int findoption(const char *s, const struct locale *lang);
param_t findparam(const char *s, const struct locale *lang);
@ -73,23 +67,9 @@ struct param;
int distribute(int old, int new_value, int n);
void init_locale(struct locale *lang);
int newunitid(void);
int forbiddenid(int id);
int newcontainerid(void);
int getunit(const struct region * r, const struct faction * f, struct unit **uresult);
int read_unitid(const struct faction *f, const struct region *r);
int alliedunit(const struct unit *u, const struct faction *f2,
int mode);
int alliedfaction(const struct plane *pl, const struct faction *f,
const struct faction *f2, int mode);
int alliedgroup(const struct plane *pl, const struct faction *f,
const struct faction *f2, const struct ally *sf, int mode);
struct faction *getfaction(void);
char *untilde(char *s);
typedef int(*cmp_building_cb) (const struct building * b,
@ -119,11 +99,8 @@ struct param;
#define GIVE_DEFAULT (GIVE_SELF|GIVE_PEASANTS|GIVE_LUXURIES|GIVE_HERBS|GIVE_GOODS)
int rule_give(void);
bool has_limited_skills(const struct unit *u);
const struct race *findrace(const char *, const struct locale *);
bool unit_has_cursed_item(const struct unit *u);
/* grammatik-flags: */
#define GF_NONE 0
/* singular, ohne was dran */
@ -157,15 +134,10 @@ struct param;
/* Verhindert Abbau von Resourcen mit RTF_LIMITED */
#define GUARD_ALL 0xFFFF
void setstatus(struct unit *u, int status);
/* !< sets combatstatus of a unit */
int besieged(const struct unit *u);
int maxworkingpeasants(const struct region *r);
bool has_horses(const struct unit *u);
bool markets_module(void);
int wage(const struct region *r, const struct faction *f,
const struct race *rc, int in_turn);
int maintenance_cost(const struct unit *u);
const char *datapath(void);
void set_datapath(const char *path);
@ -200,8 +172,6 @@ struct param;
int status;
} helpmode;
const char *dbrace(const struct race *rc);
void set_param(struct param **p, const char *key, const char *value);
const char *get_param(const struct param *p, const char *key);
int get_param_int(const struct param *p, const char *key, int def);
@ -220,9 +190,6 @@ struct param;
int LongHunger(const struct unit *u);
int NewbieImmunity(void);
bool IsImmune(const struct faction *f);
int AllianceAuto(void); /* flags that allied factions get automatically */
int AllianceRestricted(void); /* flags restricted to allied factions */
int HelpMask(void); /* flags restricted to allied factions */
struct order *default_order(const struct locale *lang);
void set_default_order(int kwd);

View File

@ -30,6 +30,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "plane.h"
#include "race.h"
#include "region.h"
#include "save.h"
#include "spellbook.h"
#include "terrain.h"
#include "unit.h"
@ -44,13 +45,15 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/lists.h>
#include <util/language.h>
#include <util/log.h>
#include <quicklist.h>
#include <util/parser.h>
#include <util/resolve.h>
#include <util/rng.h>
#include <util/variant.h>
#include <util/unicode.h>
#include <attributes/otherfaction.h>
#include <quicklist.h>
#include <storage.h>
/* libc includes */
@ -151,6 +154,11 @@ faction *findfaction(int n)
return f;
}
faction *getfaction(void)
{
return findfaction(getid());
}
void set_show_item(faction * f, const struct item_type *itype)
{
attrib *a = a_add(&f->attribs, a_new(&at_showitem));
@ -773,3 +781,65 @@ int count_maxmigrants(const faction * f)
}
return 0;
}
static void init_maxmagicians(struct attrib *a)
{
a->data.i = MAXMAGICIANS;
}
attrib_type at_maxmagicians = {
"maxmagicians",
init_maxmagicians,
NULL,
NULL,
a_writeint,
a_readint,
ATF_UNIQUE
};
int max_magicians(const faction * f)
{
int m = config_get_int("rules.maxskills.magic", MAXMAGICIANS);
attrib *a;
if ((a = a_find(f->attribs, &at_maxmagicians)) != NULL) {
m = a->data.i;
}
if (f->race == get_race(RC_ELF))
++m;
return m;
}
#define DMAXHASH 7919
typedef struct dead {
struct dead *nexthash;
faction *f;
int no;
} dead;
static dead *deadhash[DMAXHASH];
void dhash(int no, faction * f)
{
dead *hash = (dead *)calloc(1, sizeof(dead));
dead *old = deadhash[no % DMAXHASH];
hash->no = no;
hash->f = f;
deadhash[no % DMAXHASH] = hash;
hash->nexthash = old;
}
faction *dfindhash(int no)
{
dead *old;
if (no < 0)
return 0;
for (old = deadhash[no % DMAXHASH]; old; old = old->nexthash) {
if (old->no == no) {
return old->f;
}
}
return 0;
}

View File

@ -29,7 +29,9 @@ extern "C" {
struct alliance;
struct item;
struct seen_region;
struct attrib_type;
extern struct attrib_type at_maxmagicians;
/* SMART_INTERVALS: define to speed up finding the interval of regions that a
faction is in. defining this speeds up the turn by 30-40% */
#define SMART_INTERVALS
@ -173,7 +175,13 @@ extern "C" {
int count_maxmigrants(const struct faction * f);
int count_all(const struct faction * f);
int count_units(const struct faction * f);
int max_magicians(const struct faction * f);
struct faction *getfaction(void);
/* looking up dead factions: */
void dhash(int no, struct faction * f);
struct faction *dfindhash(int no);
#ifdef __cplusplus
}

View File

@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <kernel/config.h>
#include "pool.h"
#include "ally.h"
#include "faction.h"
#include "item.h"
#include "order.h"

View File

@ -301,3 +301,20 @@ variant read_race_reference(struct storage *store)
assert(result.v != NULL);
return result;
}
/** Returns the English name of the race, which is what the database uses.
*/
const char *dbrace(const struct race *rc)
{
static char zText[32]; // FIXME: static return value
char *zPtr = zText;
/* the english names are all in ASCII, so we don't need to worry about UTF8 */
strlcpy(zText, (const char *)LOC(get_locale("en"), rc_name_s(rc, NAME_SINGULAR)), sizeof(zText));
while (*zPtr) {
*zPtr = (char)(toupper(*zPtr));
++zPtr;
}
return zText;
}

View File

@ -233,8 +233,8 @@ extern "C" {
#define BF_INV_NONMAGIC (1<<5) /* Immun gegen nichtmagischen Schaden */
#define BF_CANATTACK (1<<6) /* Kann keine ATTACKIERE Befehle ausfuehren */
extern int unit_old_max_hp(struct unit *u);
extern const char *racename(const struct locale *lang, const struct unit *u,
int unit_old_max_hp(struct unit *u);
const char *racename(const struct locale *lang, const struct unit *u,
const race * rc);
#define omniscient(f) ((f)->race==get_race(RC_ILLUSION) || (f)->race==get_race(RC_TEMPLATE))
@ -244,19 +244,20 @@ extern "C" {
#define humanoidrace(rc) (fval((rc), RCF_UNDEAD) || (rc)==get_race(RC_DRACOID) || playerrace(rc))
#define illusionaryrace(rc) (fval(rc, RCF_ILLUSIONARY))
extern bool allowed_dragon(const struct region *src,
bool allowed_dragon(const struct region *src,
const struct region *target);
extern bool r_insectstalled(const struct region *r);
bool r_insectstalled(const struct region *r);
extern void write_race_reference(const struct race *rc,
void write_race_reference(const struct race *rc,
struct storage *store);
extern variant read_race_reference(struct storage *store);
variant read_race_reference(struct storage *store);
extern const char *raceprefix(const struct unit *u);
const char *raceprefix(const struct unit *u);
extern void give_starting_equipment(const struct equipment *eq,
void give_starting_equipment(const struct equipment *eq,
struct unit *u);
const char *dbrace(const struct race *rc);
#ifdef __cplusplus
}

View File

@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <kernel/config.h>
#include "unit.h"
#include "ally.h"
#include "building.h"
#include "faction.h"
#include "group.h"
@ -54,6 +55,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/language.h>
#include <util/lists.h>
#include <util/log.h>
#include <util/parser.h>
#include <util/resolve.h>
#include <util/rng.h>
#include <util/variant.h>
@ -62,6 +64,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* libc includes */
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
@ -180,40 +183,6 @@ unit *ufindhash(int uid)
return NULL;
}
#define DMAXHASH 7919
typedef struct dead {
struct dead *nexthash;
faction *f;
int no;
} dead;
static dead *deadhash[DMAXHASH];
static void dhash(int no, faction * f)
{
dead *hash = (dead *)calloc(1, sizeof(dead));
dead *old = deadhash[no % DMAXHASH];
hash->no = no;
hash->f = f;
deadhash[no % DMAXHASH] = hash;
hash->nexthash = old;
}
faction *dfindhash(int no)
{
dead *old;
if (no < 0)
return 0;
for (old = deadhash[no % DMAXHASH]; old; old = old->nexthash) {
if (old->no == no) {
return old->f;
}
}
return 0;
}
typedef struct buddy {
struct buddy *next;
int number;
@ -1935,3 +1904,141 @@ void produceexp(struct unit *u, skill_t sk, int n)
produceexp_ex(u, sk, n, learn_skill);
}
/* ID's für Einheiten und Zauber */
int newunitid(void)
{
int random_unit_no;
int start_random_no;
random_unit_no = 1 + (rng_int() % MAX_UNIT_NR);
start_random_no = random_unit_no;
while (ufindhash(random_unit_no) || dfindhash(random_unit_no)
|| cfindhash(random_unit_no)
|| forbiddenid(random_unit_no)) {
random_unit_no++;
if (random_unit_no == MAX_UNIT_NR + 1) {
random_unit_no = 1;
}
if (random_unit_no == start_random_no) {
random_unit_no = (int)MAX_UNIT_NR + 1;
}
}
return random_unit_no;
}
static int read_newunitid(const faction * f, const region * r)
{
int n;
unit *u2;
n = getid();
if (n == 0)
return -1;
u2 = findnewunit(r, f, n);
if (u2)
return u2->no;
return -1;
}
int read_unitid(const faction * f, const region * r)
{
char token[16];
const char *s = gettoken(token, sizeof(token));
/* Da s nun nur einen string enthaelt, suchen wir ihn direkt in der
* paramliste. machen wir das nicht, dann wird getnewunit in s nach der
* nummer suchen, doch dort steht bei temp-units nur "temp" drinnen! */
if (!s || *s == 0 || !isalnum(*s)) {
return -1;
}
if (isparam(s, f->locale, P_TEMP)) {
return read_newunitid(f, r);
}
return atoi36((const char *)s);
}
int getunit(const region * r, const faction * f, unit **uresult)
{
unit *u2 = NULL;
int n = read_unitid(f, r);
int result = GET_NOTFOUND;
if (n == 0) {
result = GET_PEASANTS;
}
else if (n > 0) {
u2 = findunit(n);
if (u2 != NULL && u2->region == r) {
/* there used to be a 'u2->flags & UFL_ISNEW || u2->number>0' condition
* here, but it got removed because of a bug that made units disappear:
* http://eressea.upb.de/mantis/bug_view_page.php?bug_id=0000172
*/
result = GET_UNIT;
}
else {
u2 = NULL;
}
}
if (uresult) {
*uresult = u2;
}
return result;
}
int besieged(const unit * u)
{
/* belagert kann man in schiffen und burgen werden */
return (u && !keyword_disabled(K_BESIEGE)
&& u->building && u->building->besieged
&& u->building->besieged >= u->building->size * SIEGEFACTOR);
}
bool has_horses(const unit * u)
{
item *itm = u->items;
for (; itm; itm = itm->next) {
if (itm->type->flags & ITF_ANIMAL)
return true;
}
return false;
}
void setstatus(unit *u, int status)
{
assert(status >= ST_AGGRO && status <= ST_FLEE);
if (u->status != status) {
u->status = (status_t)status;
}
}
#define MAINTENANCE 10
int maintenance_cost(const struct unit *u)
{
if (u == NULL)
return MAINTENANCE;
if (global.functions.maintenance) {
int retval = global.functions.maintenance(u);
if (retval >= 0)
return retval;
}
return u_race(u)->maintenance * u->number;
}
static skill_t limited_skills[] = { SK_MAGIC, SK_ALCHEMY, SK_TACTICS, SK_SPY, SK_HERBALISM, NOSKILL };
bool has_limited_skills(const struct unit * u)
{
int i, j;
for (i = 0; i != u->skill_size; ++i) {
skill *sv = u->skills + i;
for (j = 0; limited_skills[j] != NOSKILL; ++j) {
if (sv->id == limited_skills[j]) {
return true;
}
}
}
return false;
}

View File

@ -206,7 +206,6 @@ extern "C" {
/* cleanup code for this module */
void free_units(void);
struct faction *dfindhash(int no);
void u_setfaction(struct unit *u, struct faction *f);
void set_number(struct unit *u, int count);
@ -256,6 +255,22 @@ extern "C" {
bool unit_name_equals_race(const struct unit *u);
bool unit_can_study(const struct unit *u);
/* getunit results: */
#define GET_UNIT 0
#define GET_NOTFOUND 1
#define GET_PEASANTS 2
int getunit(const struct region * r, const struct faction * f, struct unit **uresult);
int newunitid(void);
int read_unitid(const struct faction *f, const struct region *r);
void setstatus(struct unit *u, int status);
/* !< sets combatstatus of a unit */
int besieged(const struct unit *u);
bool has_horses(const struct unit *u);
int maintenance_cost(const struct unit *u);
bool has_limited_skills(const struct unit *u);
#ifdef __cplusplus
}
#endif

View File

@ -392,6 +392,28 @@ static void test_inside_building(CuTest *tc) {
test_cleanup();
}
static void test_limited_skills(CuTest *tc) {
unit *u;
test_cleanup();
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
CuAssertIntEquals(tc, false, has_limited_skills(u));
set_level(u, SK_ENTERTAINMENT, 1);
CuAssertIntEquals(tc, false, has_limited_skills(u));
u->skills->id = SK_ALCHEMY;
CuAssertIntEquals(tc, true, has_limited_skills(u));
u->skills->id = SK_MAGIC;
CuAssertIntEquals(tc, true, has_limited_skills(u));
u->skills->id = SK_TACTICS;
CuAssertIntEquals(tc, true, has_limited_skills(u));
u->skills->id = SK_HERBALISM;
CuAssertIntEquals(tc, true, has_limited_skills(u));
u->skills->id = SK_SPY;
CuAssertIntEquals(tc, true, has_limited_skills(u));
u->skills->id = SK_TAXING;
CuAssertIntEquals(tc, false, has_limited_skills(u));
test_cleanup();
}
CuSuite *get_unit_suite(void)
{
CuSuite *suite = CuSuiteNew();
@ -412,5 +434,6 @@ CuSuite *get_unit_suite(void)
SUITE_ADD_TEST(suite, test_age_familiar);
SUITE_ADD_TEST(suite, test_inside_building);
SUITE_ADD_TEST(suite, test_produceexp);
SUITE_ADD_TEST(suite, test_limited_skills);
return suite;
}

View File

@ -478,7 +478,16 @@ static int count_race(const region * r, const race * rc)
return c;
}
extern struct attrib_type at_germs;
attrib_type at_germs = {
"germs",
DEFAULT_INIT,
DEFAULT_FINALIZE,
DEFAULT_AGE,
a_writeshorts,
a_readshorts,
ATF_UNIQUE
};
static void
growing_trees_e3(region * r, const int current_season,

View File

@ -34,6 +34,7 @@ extern "C" {
struct attrib_type;
extern struct attrib_type at_germs;
extern int dropouts[2];
extern int *age;

View File

@ -24,6 +24,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "skill.h"
#include "laws.h"
#include <kernel/ally.h>
#include <kernel/building.h>
#include <kernel/curse.h>
#include <kernel/faction.h>

View File

@ -29,6 +29,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "lighthouse.h"
#include "piracy.h"
#include <kernel/ally.h>
#include <kernel/build.h>
#include <kernel/building.h>
#include <kernel/connection.h>

View File

@ -6,6 +6,7 @@
#include "keyword.h"
#include "move.h"
#include <kernel/ally.h>
#include <kernel/faction.h>
#include <kernel/messages.h>
#include <kernel/order.h>

View File

@ -26,6 +26,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "donations.h"
/* kernel includes */
#include <kernel/ally.h>
#include <kernel/alliance.h>
#include <kernel/connection.h>
#include <kernel/building.h>

View File

@ -25,6 +25,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "move.h"
#include "alchemy.h"
#include <kernel/ally.h>
#include <kernel/building.h>
#include <kernel/curse.h>
#include <kernel/faction.h>

View File

@ -1,6 +1,7 @@
#include <platform.h>
#include "upkeep.h"
#include <kernel/ally.h>
#include <kernel/faction.h>
#include <kernel/config.h>
#include <kernel/item.h>