From 2da1d112776b76426f9973e0f35938f2dfcc4d03 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 13 Dec 2014 11:30:34 +0100 Subject: [PATCH] move chaos to a separate module (it is an old E2 feature) --- src/CMakeLists.txt | 1 + src/battle.c | 11 +- src/bind_region.c | 6 +- src/chaos.c | 256 ++++++++++++++++++++++++++++++++++++++++++++ src/chaos.h | 38 +++++++ src/kernel/config.c | 1 - src/kernel/region.c | 52 ++------- src/kernel/region.h | 1 - src/monsters.c | 7 +- src/randenc.c | 168 +---------------------------- 10 files changed, 316 insertions(+), 225 deletions(-) create mode 100644 src/chaos.c create mode 100644 src/chaos.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bf64fa393..f04c0cffc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,6 +87,7 @@ set (ERESSEA_SRC morale.c monster.c randenc.c + chaos.c report.c spy.c study.c diff --git a/src/battle.c b/src/battle.c index c7ccf2ae8..feded87f9 100644 --- a/src/battle.c +++ b/src/battle.c @@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "battle.h" #include "alchemy.h" +#include "chaos.h" #include "move.h" #include "laws.h" #include "skill.h" @@ -81,13 +82,8 @@ static FILE *bdebug; #define CATAPULT_STRUCTURAL_DAMAGE #define BASE_CHANCE 70 /* 70% Basis-Überlebenschance */ -#ifdef NEW_COMBATSKILLS_RULE #define TDIFF_CHANGE 5 /* 5% höher pro Stufe */ #define DAMAGE_QUOTIENT 2 /* damage += skilldiff/DAMAGE_QUOTIENT */ -#else -#define TDIFF_CHANGE 10 -# define DAMAGE_QUOTIENT 1 /* damage += skilldiff/DAMAGE_QUOTIENT */ -#endif #undef DEBUG_FAST /* should be disabled when b->fast and b->rowcache works */ #define DEBUG_SELECT /* should be disabled if select_enemy works */ @@ -2615,7 +2611,7 @@ static void battle_effects(battle * b, int dead_players) _min(rpeasants(r), (int)(dead_players * PopulationDamage())); if (dead_peasants) { deathcounts(r, dead_peasants + dead_players); - chaoscounts(r, dead_peasants / 2); + add_chaoscount(r, dead_peasants / 2); rsetpeasants(r, rpeasants(r) - dead_peasants); } } @@ -2899,12 +2895,11 @@ static void aftermath(battle * b) static void battle_punit(unit * u, battle * b) { bfaction *bf; - strlist *S, *x; for (bf = b->factions; bf; bf = bf->next) { faction *f = bf->faction; + strlist *S = 0, *x; - S = 0; spunit(&S, f, u, 4, see_battle); for (x = S; x; x = x->next) { fbattlerecord(b, f, x->s); diff --git a/src/bind_region.c b/src/bind_region.c index e10b22cfd..10faa794a 100644 --- a/src/bind_region.c +++ b/src/bind_region.c @@ -16,6 +16,8 @@ without prior permission by the authors of Eressea. #include "bind_ship.h" #include "bind_building.h" +#include "chaos.h" + #include #include #include @@ -370,7 +372,7 @@ static int tolua_region_get_resource(lua_State * L) result = deathcount(r); break; case 4: - result = chaoscount(r); + result = get_chaoscount(r); break; } } else { @@ -406,7 +408,7 @@ static int tolua_region_set_resource(lua_State * L) deathcounts(r, value - deathcount(r)); break; case 4: - chaoscounts(r, value - chaoscount(r)); + add_chaoscount(r, value - get_chaoscount(r)); break; } } else { diff --git a/src/chaos.c b/src/chaos.c new file mode 100644 index 000000000..abf0171e2 --- /dev/null +++ b/src/chaos.c @@ -0,0 +1,256 @@ +/* +Copyright (c) 1998-2010, Enno Rehling +Katja Zedel + +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 +#include +#include "chaos.h" +#include "monster.h" +#include "move.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +/*********************/ +/* at_chaoscount */ +/*********************/ +attrib_type at_chaoscount = { + "get_chaoscount", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, + a_writeint, + a_readint, + ATF_UNIQUE +}; + +int get_chaoscount(const region * r) +{ + attrib *a = a_find(r->attribs, &at_chaoscount); + if (!a) + return 0; + return a->data.i; +} + +void add_chaoscount(region * r, int fallen) +{ + attrib *a; + + if (fallen == 0) + return; + + a = a_find(r->attribs, &at_chaoscount); + if (!a) + a = a_add(&r->attribs, a_new(&at_chaoscount)); + a->data.i += fallen; + + if (a->data.i <= 0) + a_remove(&r->attribs, a); +} + +static const terrain_type *chaosterrain(void) +{ + static const terrain_type **types; + static int numtypes; + + if (numtypes == 0) { + const terrain_type *terrain; + for (terrain = terrains(); terrain != NULL; terrain = terrain->next) { + if (fval(terrain, LAND_REGION) && terrain->herbs) { + ++numtypes; + } + } + if (numtypes > 0) { + types = malloc(sizeof(terrain_type *) * numtypes); + numtypes = 0; + for (terrain = terrains(); terrain != NULL; terrain = terrain->next) { + if (fval(terrain, LAND_REGION) && terrain->herbs) { + types[numtypes++] = terrain; + } + } + } + } + if (numtypes > 0) { + return types[rng_int() % numtypes]; + } + return NULL; +} + +static unit *random_unit(const region * r) +{ + int c = 0; + int n; + unit *u; + + for (u = r->units; u; u = u->next) { + if (u_race(u) != get_race(RC_SPELL)) { + c += u->number; + } + } + + if (c == 0) { + return NULL; + } + n = rng_int() % c; + c = 0; + u = r->units; + + while (u && c < n) { + if (u_race(u) != get_race(RC_SPELL)) { + c += u->number; + } + u = u->next; + } + + return u; +} + +static void chaos(region * r) +{ + if (rng_int() % 100 < 8) { + switch (rng_int() % 3) { + case 0: /* Untote */ + if (!fval(r->terrain, SEA_REGION)) { + unit *u = random_unit(r); + if (u && playerrace(u_race(u))) { + ADDMSG(&u->faction->msgs, msg_message("chaos_disease", "unit", u)); + u_setfaction(u, get_monsters()); + u_setrace(u, get_race(RC_GHOUL)); + } + } + break; + case 1: /* Drachen */ + if (random_unit(r)) { + int mfac = 0; + unit *u; + switch (rng_int() % 3) { + case 0: + mfac = 100; + u = + createunit(r, get_monsters(), rng_int() % 8 + 1, + get_race(RC_FIREDRAGON)); + break; + case 1: + mfac = 500; + u = + createunit(r, get_monsters(), rng_int() % 4 + 1, + get_race(RC_DRAGON)); + break; + default: + mfac = 1000; + u = + createunit(r, get_monsters(), rng_int() % 2 + 1, + get_race(RC_WYRM)); + break; + } + if (mfac) + set_money(u, u->number * (rng_int() % mfac)); + fset(u, UFL_ISNEW | UFL_MOVED); + } + case 2: /* Terrainveränderung */ + if (!fval(r->terrain, FORBIDDEN_REGION)) { + if (!fval(r->terrain, SEA_REGION)) { + direction_t dir; + for (dir = 0; dir != MAXDIRECTIONS; ++dir) { + region *rn = rconnect(r, dir); + if (rn && fval(rn->terrain, SEA_REGION)) + break; + } + if (dir != MAXDIRECTIONS) { + ship *sh = r->ships; + unit **up; + + while (sh) { + ship *nsh = sh->next; + float dmg = + get_param_flt(global.parameters, "rules.ship.damage.atlantis", + 0.50); + damage_ship(sh, dmg); + if (sh->damage >= sh->size * DAMAGE_SCALE) { + remove_ship(&sh->region->ships, sh); + } + sh = nsh; + } + + for (up = &r->units; *up;) { + unit *u = *up; + if (u_race(u) != get_race(RC_SPELL) && u->ship == 0 && !canfly(u)) { + ADDMSG(&u->faction->msgs, msg_message("tidalwave_kill", + "region unit", r, u)); + remove_unit(up, u); + } + if (*up == u) + up = &u->next; + } + ADDMSG(&r->msgs, msg_message("tidalwave", "region", r)); + + while (r->buildings) { + remove_building(&r->buildings, r->buildings); + } + terraform_region(r, newterrain(T_OCEAN)); + } + } + else { + direction_t dir; + for (dir = 0; dir != MAXDIRECTIONS; ++dir) { + region *rn = rconnect(r, dir); + if (rn && fval(rn->terrain, SEA_REGION)) + break; + } + if (dir != MAXDIRECTIONS) { + terraform_region(r, chaosterrain()); + } + } + } + } + } +} + +void chaos_update(void) { + region *r; + /* Chaos */ + for (r = regions; r; r = r->next) { + int i; + + if (fval(r, RF_CHAOTIC)) { + chaos(r); + } + i = get_chaoscount(r); + if (i) { + add_chaoscount(r, -(int)(i * ((double)(rng_int() % 10)) / 100.0)); + } + } +} + +void chaos_init(void) { + at_register(&at_chaoscount); +} diff --git a/src/chaos.h b/src/chaos.h new file mode 100644 index 000000000..556116b8a --- /dev/null +++ b/src/chaos.h @@ -0,0 +1,38 @@ +/* +Copyright (c) 1998-2014, Enno Rehling +Katja Zedel + +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. +**/ + +#ifndef H_GC_CHAOS +#define H_GC_CHAOS +#ifdef __cplusplus +extern "C" { +#endif + + struct region; + + extern struct attrib_type at_chaoscount; + + void chaos_init(void); + void chaos_update(void); + + int get_chaoscount(const struct region * r); + void add_chaoscount(struct region * r, int deaths); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/kernel/config.c b/src/kernel/config.c index 3dd22b159..42cff7f71 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -2153,7 +2153,6 @@ void attrib_init(void) /* neue REGION-Attribute */ at_register(&at_moveblock); at_register(&at_deathcount); - at_register(&at_chaoscount); at_register(&at_woodcount); /* neue UNIT-Attribute */ diff --git a/src/kernel/region.c b/src/kernel/region.c index 0736d7ba9..61f10da27 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -144,14 +144,6 @@ int deathcount(const region * r) return a->data.i; } -int chaoscount(const region * r) -{ - attrib *a = a_find(r->attribs, &at_chaoscount); - if (!a) - return 0; - return a->data.i; -} - void deathcounts(region * r, int fallen) { attrib *a; @@ -173,22 +165,6 @@ void deathcounts(region * r, int fallen) a_remove(&r->attribs, a); } -void chaoscounts(region * r, int fallen) -{ - attrib *a; - - if (fallen == 0) - return; - - a = a_find(r->attribs, &at_chaoscount); - if (!a) - a = a_add(&r->attribs, a_new(&at_chaoscount)); - a->data.i += fallen; - - if (a->data.i <= 0) - a_remove(&r->attribs, a); -} - /* Moveblock wird zur Zeit nicht über Attribute, sondern ein Bitfeld r->moveblock gemacht. Sollte umgestellt werden, wenn kompliziertere Dinge gefragt werden. */ @@ -237,8 +213,9 @@ static uidhashentry uidhash[MAXREGIONS]; struct region *findregionbyid(int uid) { int key = uid % MAXREGIONS; - while (uidhash[key].uid != 0 && uidhash[key].uid != uid) - ++key; + while (uidhash[key].uid != 0 && uidhash[key].uid != uid) { + if (++key==MAXREGIONS) key = 0; + } return uidhash[key].r; } @@ -248,8 +225,9 @@ static void unhash_uid(region * r) { int key = r->uid % MAXREGIONS; assert(r->uid); - while (uidhash[key].uid != 0 && uidhash[key].uid != r->uid) - ++key; + while (uidhash[key].uid != 0 && uidhash[key].uid != r->uid) { + if (++key == MAXREGIONS) key = 0; + } assert(uidhash[key].r == r); uidhash[key].r = NULL; } @@ -260,8 +238,9 @@ static void hash_uid(region * r) for (;;) { if (uid != 0) { int key = uid % MAXREGIONS; - while (uidhash[key].uid != 0 && uidhash[key].uid != uid) - ++key; + while (uidhash[key].uid != 0 && uidhash[key].uid != uid) { + if (++key == MAXREGIONS) key = 0; + } if (uidhash[key].uid == 0) { uidhash[key].uid = uid; uidhash[key].r = r; @@ -518,19 +497,6 @@ attrib_type at_peasantluck = { ATF_UNIQUE }; -/*********************/ -/* at_chaoscount */ -/*********************/ -attrib_type at_chaoscount = { - "chaoscount", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, - a_writeint, - a_readint, - ATF_UNIQUE -}; - /*********************/ /* at_deathcount */ /*********************/ diff --git a/src/kernel/region.h b/src/kernel/region.h index aa05853f0..df3f99b4d 100644 --- a/src/kernel/region.h +++ b/src/kernel/region.h @@ -167,7 +167,6 @@ extern "C" { extern struct attrib_type at_moveblock; extern struct attrib_type at_peasantluck; extern struct attrib_type at_horseluck; - extern struct attrib_type at_chaoscount; extern struct attrib_type at_woodcount; extern struct attrib_type at_deathcount; extern struct attrib_type at_travelunit; diff --git a/src/monsters.c b/src/monsters.c index 659c47018..843b9d60b 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -23,6 +23,7 @@ #include #include "economy.h" +#include "chaos.h" #include "give.h" #include "monster.h" #include "laws.h" @@ -867,7 +868,6 @@ void plan_monsters(faction * f) } if (long_order) { addlist(&u->orders, long_order); -// u->thisorder = long_order; } } } @@ -876,10 +876,7 @@ void plan_monsters(faction * f) static double chaosfactor(region * r) { - attrib *a = a_find(r->attribs, &at_chaoscount); - if (!a) - return 0; - return ((double)a->data.i / 1000.0); + return fval(r, RF_CHAOTIC) ? ((double)(1 + get_chaoscount(r)) / 1000.0) : 0.0; } static int nrand(int start, int sub) diff --git a/src/randenc.c b/src/randenc.c index d5483fc08..f611ba9ee 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -24,6 +24,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "monster.h" #include "move.h" #include "alchemy.h" +#include "chaos.h" /* kernel includes */ #include @@ -417,159 +418,6 @@ void encounters(void) } } -static const terrain_type *chaosterrain(void) -{ - static const terrain_type **types; - static int numtypes; - - if (numtypes == 0) { - const terrain_type *terrain; - for (terrain = terrains(); terrain != NULL; terrain = terrain->next) { - if (fval(terrain, LAND_REGION) && terrain->herbs) { - ++numtypes; - } - } - types = malloc(sizeof(terrain_type) * numtypes); - numtypes = 0; - for (terrain = terrains(); terrain != NULL; terrain = terrain->next) { - if (fval(terrain, LAND_REGION) && terrain->herbs) { - types[numtypes++] = terrain; - } - } - } - return types[rng_int() % numtypes]; -} - -static unit *random_unit(const region * r) -{ - int c = 0; - int n; - unit *u; - - for (u = r->units; u; u = u->next) { - if (u_race(u) != get_race(RC_SPELL)) { - c += u->number; - } - } - - if (c == 0) { - return NULL; - } - n = rng_int() % c; - c = 0; - u = r->units; - - while (u && c < n) { - if (u_race(u) != get_race(RC_SPELL)) { - c += u->number; - } - u = u->next; - } - - return u; -} - -void chaos(region * r) -{ - if (rng_int() % 100 < 8) { - switch (rng_int() % 3) { - case 0: /* Untote */ - if (!fval(r->terrain, SEA_REGION)) { - unit *u = random_unit(r); - if (u && playerrace(u_race(u))) { - ADDMSG(&u->faction->msgs, msg_message("chaos_disease", "unit", u)); - u_setfaction(u, get_monsters()); - u_setrace(u, get_race(RC_GHOUL)); - } - } - break; - case 1: /* Drachen */ - if (random_unit(r)) { - int mfac = 0; - unit *u; - switch (rng_int() % 3) { - case 0: - mfac = 100; - u = - createunit(r, get_monsters(), rng_int() % 8 + 1, - get_race(RC_FIREDRAGON)); - break; - case 1: - mfac = 500; - u = - createunit(r, get_monsters(), rng_int() % 4 + 1, - get_race(RC_DRAGON)); - break; - default: - mfac = 1000; - u = - createunit(r, get_monsters(), rng_int() % 2 + 1, - get_race(RC_WYRM)); - break; - } - if (mfac) - set_money(u, u->number * (rng_int() % mfac)); - fset(u, UFL_ISNEW | UFL_MOVED); - } - case 2: /* Terrainveränderung */ - if (!fval(r->terrain, FORBIDDEN_REGION)) { - if (!fval(r->terrain, SEA_REGION)) { - direction_t dir; - for (dir = 0; dir != MAXDIRECTIONS; ++dir) { - region *rn = rconnect(r, dir); - if (rn && fval(rn->terrain, SEA_REGION)) - break; - } - if (dir != MAXDIRECTIONS) { - ship *sh = r->ships; - unit **up; - - while (sh) { - ship *nsh = sh->next; - float dmg = - get_param_flt(global.parameters, "rules.ship.damage.atlantis", - 0.50); - damage_ship(sh, dmg); - if (sh->damage >= sh->size * DAMAGE_SCALE) { - remove_ship(&sh->region->ships, sh); - } - sh = nsh; - } - - for (up = &r->units; *up;) { - unit *u = *up; - if (u_race(u) != get_race(RC_SPELL) && u->ship == 0 && !canfly(u)) { - ADDMSG(&u->faction->msgs, msg_message("tidalwave_kill", - "region unit", r, u)); - remove_unit(up, u); - } - if (*up == u) - up = &u->next; - } - ADDMSG(&r->msgs, msg_message("tidalwave", "region", r)); - - while (r->buildings) { - remove_building(&r->buildings, r->buildings); - } - terraform_region(r, newterrain(T_OCEAN)); - } - } - else { - direction_t dir; - for (dir = 0; dir != MAXDIRECTIONS; ++dir) { - region *rn = rconnect(r, dir); - if (rn && fval(rn->terrain, SEA_REGION)) - break; - } - if (dir != MAXDIRECTIONS) { - terraform_region(r, chaosterrain()); - } - } - } - } - } -} - static int nb_armor(const unit * u, int index) { const item *itm; @@ -611,6 +459,7 @@ damage_unit(unit * u, const char *dam, bool physical, bool magic) return 0; } + assert(u->number > u->hp); h = u->hp / u->number; /* HP verteilen */ for (i = 0; i < u->number; i++) @@ -1325,18 +1174,7 @@ void randomevents(void) } } - /* Chaos */ - for (r = regions; r; r = r->next) { - int i; - - if (fval(r, RF_CHAOTIC)) { - chaos(r); - } - i = chaoscount(r); - if (i) { - chaoscounts(r, -(int)(i * ((double)(rng_int() % 10)) / 100.0)); - } - } + chaos_update(); #ifdef HERBS_ROT rotting_herbs(); #endif