diff --git a/src/attributes/attributes.c b/src/attributes/attributes.c index 605616ef1..afe899b0f 100644 --- a/src/attributes/attributes.c +++ b/src/attributes/attributes.c @@ -20,12 +20,17 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #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 +#include +#include #include #include +#include #include #include #include @@ -47,13 +56,67 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* util includes */ #include +#include + +#include 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); diff --git a/src/attributes/otherfaction.c b/src/attributes/otherfaction.c index 76d035dd1..8e4e7a6af 100644 --- a/src/attributes/otherfaction.c +++ b/src/attributes/otherfaction.c @@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "otherfaction.h" +#include #include #include #include diff --git a/src/battle.c b/src/battle.c index 6e642ff00..57004514b 100644 --- a/src/battle.c +++ b/src/battle.c @@ -27,6 +27,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "skill.h" #include "monster.h" +#include #include #include #include diff --git a/src/economy.c b/src/economy.c index e4e52e0ce..be26c5d57 100644 --- a/src/economy.c +++ b/src/economy.c @@ -35,6 +35,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "calendar.h" /* kernel includes */ +#include #include #include #include diff --git a/src/give.c b/src/give.c index 634a37be6..52b1cda34 100644 --- a/src/give.c +++ b/src/give.c @@ -18,6 +18,7 @@ #include "laws.h" /* kernel includes */ +#include #include #include #include @@ -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. */ diff --git a/src/kernel/ally.c b/src/kernel/ally.c index ed53cbce4..d53973328 100644 --- a/src/kernel/ally.c +++ b/src/kernel/ally.c @@ -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 +#include +#include #include 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; +} + diff --git a/src/kernel/ally.h b/src/kernel/ally.h index 55f8dc935..58d6ff4a8 100644 --- a/src/kernel/ally.h +++ b/src/kernel/ally.h @@ -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 diff --git a/src/kernel/build.c b/src/kernel/build.c index 7c387cb10..98ca2b28e 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -28,6 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "lighthouse.h" /* kernel includes */ +#include #include #include #include diff --git a/src/kernel/config.c b/src/kernel/config.c index aa67d3fb0..56022ef74 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -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 #include #include @@ -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]; diff --git a/src/kernel/config.h b/src/kernel/config.h index 14cfa6d2c..257de940d 100644 --- a/src/kernel/config.h +++ b/src/kernel/config.h @@ -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); diff --git a/src/kernel/faction.c b/src/kernel/faction.c index 288c54569..6bc28e3e6 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -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 #include #include -#include +#include #include #include #include #include + #include +#include #include /* 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; +} diff --git a/src/kernel/faction.h b/src/kernel/faction.h index afeef37d3..d22763d96 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -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 } diff --git a/src/kernel/pool.c b/src/kernel/pool.c index 442553c28..6ceeda63d 100644 --- a/src/kernel/pool.c +++ b/src/kernel/pool.c @@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "pool.h" +#include "ally.h" #include "faction.h" #include "item.h" #include "order.h" diff --git a/src/kernel/race.c b/src/kernel/race.c index 7d881fe7f..07de520ab 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -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; +} + diff --git a/src/kernel/race.h b/src/kernel/race.h index 0ae925c5d..c994746d9 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -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, - struct storage *store); - extern variant read_race_reference(struct storage *store); + void write_race_reference(const struct race *rc, + 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, - struct unit *u); + void give_starting_equipment(const struct equipment *eq, + struct unit *u); + const char *dbrace(const struct race *rc); #ifdef __cplusplus } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index bc403909c..64db18193 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #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 #include #include +#include #include #include #include @@ -62,6 +64,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* libc includes */ #include +#include #include #include #include @@ -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; +} + diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 7f8cca095..e2dac5abe 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -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 diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 6e2b584cc..fc0336c71 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -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; } diff --git a/src/laws.c b/src/laws.c index f69af5649..9615706a5 100755 --- a/src/laws.c +++ b/src/laws.c @@ -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, diff --git a/src/laws.h b/src/laws.h index bc9afc106..e245f3c01 100755 --- a/src/laws.h +++ b/src/laws.h @@ -34,6 +34,7 @@ extern "C" { struct attrib_type; extern struct attrib_type at_germs; + extern int dropouts[2]; extern int *age; diff --git a/src/magic.c b/src/magic.c index 510240a74..065a58e7c 100644 --- a/src/magic.c +++ b/src/magic.c @@ -24,6 +24,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "skill.h" #include "laws.h" +#include #include #include #include diff --git a/src/move.c b/src/move.c index 45a0c1fb8..063635178 100644 --- a/src/move.c +++ b/src/move.c @@ -29,6 +29,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "lighthouse.h" #include "piracy.h" +#include #include #include #include diff --git a/src/piracy.c b/src/piracy.c index e9bcb6105..8b215d718 100644 --- a/src/piracy.c +++ b/src/piracy.c @@ -6,6 +6,7 @@ #include "keyword.h" #include "move.h" +#include #include #include #include diff --git a/src/reports.c b/src/reports.c index 29b459f20..24ff6dcb2 100644 --- a/src/reports.c +++ b/src/reports.c @@ -26,6 +26,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "donations.h" /* kernel includes */ +#include #include #include #include diff --git a/src/study.c b/src/study.c index 9d3edddb1..a20959408 100644 --- a/src/study.c +++ b/src/study.c @@ -25,6 +25,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "move.h" #include "alchemy.h" +#include #include #include #include diff --git a/src/upkeep.c b/src/upkeep.c index da9cbff74..193c68480 100644 --- a/src/upkeep.c +++ b/src/upkeep.c @@ -1,6 +1,7 @@ #include #include "upkeep.h" +#include #include #include #include