eliminate race.parameters.

move all special properties to race.options
This commit is contained in:
Enno Rehling 2017-02-06 09:46:36 +01:00
parent 998dcffab2
commit 28c951bdfd
7 changed files with 84 additions and 39 deletions

View File

@ -86,8 +86,12 @@ typedef struct rcoption {
enum { enum {
RCO_NONE, RCO_NONE,
RCO_SCARE, RCO_SCARE, // races that scare and eat peasants
RCO_OTHER RCO_OTHER, // may recruit from another race
RCO_STAMINA, // every n levels of stamina add +1 RC
RCO_HUNGER, // custom hunger.damage override (char *)
RCO_TRADELUX,
RCO_TRADEHERB,
}; };
static void rc_setoption(race *rc, int key, const char *value) { static void rc_setoption(race *rc, int key, const char *value) {
@ -114,9 +118,21 @@ static void rc_setoption(race *rc, int key, const char *value) {
if (key == RCO_SCARE) { if (key == RCO_SCARE) {
v->i = atoi(value); v->i = atoi(value);
} }
else if (key == RCO_STAMINA) {
v->i = atoi(value);
}
else if (key == RCO_OTHER) { else if (key == RCO_OTHER) {
v->v = rc_get_or_create(value); v->v = rc_get_or_create(value);
} }
else if (key == RCO_HUNGER) {
v->v = strdup(value);
}
else if (key == RCO_TRADEHERB) {
v->i = atoi(value);
}
else if (key == RCO_TRADELUX) {
v->i = atoi(value);
}
} }
static variant *rc_getoption(const race *rc, int key) { static variant *rc_getoption(const race *rc, int key) {
@ -238,12 +254,20 @@ void free_races(void) {
while (races) { while (races) {
int i; int i;
race * rc = races->next; race * rc = races->next;
rcoption * opt = races->options;
if (opt) {
for (i=0;i!=MAXOPTIONS && opt->key[i]!=RCO_NONE;++i) {
if (opt->key[i]==RCO_HUNGER) {
free(opt->value[i].v);
}
}
free(opt);
}
for (i = 0; races->attack[i].type!=AT_NONE; ++i) { for (i = 0; races->attack[i].type!=AT_NONE; ++i) {
spellref_free(races->attack[i].data.sp); spellref_free(races->attack[i].data.sp);
} }
spellref_free(races->precombatspell); spellref_free(races->precombatspell);
free_params(&races->parameters);
free(xrefs); free(xrefs);
xrefs = 0; xrefs = 0;
free(races->_name); free(races->_name);
@ -344,9 +368,16 @@ double rc_maxaura(const race *rc) {
return rc->maxaura / 100.0; return rc->maxaura / 100.0;
} }
const char * rc_hungerdamage(const race *rc)
{
variant *v = rc_getoption(rc, RCO_HUNGER);
return v ? (const char *)v->v : NULL;
}
int rc_armor_bonus(const race *rc) int rc_armor_bonus(const race *rc)
{ {
return get_param_int(rc->parameters, "armor.stamina", 0); variant *v = rc_getoption(rc, RCO_STAMINA);
return v ? v->i : 0;
} }
int rc_scare(const struct race *rc) int rc_scare(const struct race *rc)
@ -355,6 +386,24 @@ int rc_scare(const struct race *rc)
return v ? v->i : 0; return v ? v->i : 0;
} }
int rc_luxury_trade(const struct race *rc)
{
if (rc) {
variant *v = rc_getoption(rc, RCO_TRADELUX);
if (v) return v->i;
}
return 1000;
}
int rc_herb_trade(const struct race *rc)
{
if (rc) {
variant *v = rc_getoption(rc, RCO_TRADEHERB);
if (v) return v->i;
}
return 500;
}
const race *rc_otherrace(const race *rc) const race *rc_otherrace(const race *rc)
{ {
variant *v = rc_getoption(rc, RCO_OTHER); variant *v = rc_getoption(rc, RCO_OTHER);
@ -381,8 +430,20 @@ void rc_set_param(struct race *rc, const char *key, const char *value) {
else if (strcmp(key, "ai.scare")==0) { else if (strcmp(key, "ai.scare")==0) {
rc_setoption(rc, RCO_SCARE, value); rc_setoption(rc, RCO_SCARE, value);
} }
else if (strcmp(key, "hunger.damage")==0) {
rc_setoption(rc, RCO_HUNGER, value);
}
else if (strcmp(key, "armor.stamina")==0) {
rc_setoption(rc, RCO_STAMINA, value);
}
else if (strcmp(key, "luxury_trade")==0) {
rc_setoption(rc, RCO_TRADELUX, value);
}
else if (strcmp(key, "herb_trade")==0) {
rc_setoption(rc, RCO_TRADEHERB, value);
}
else { else {
set_param(&rc->parameters, key, value); log_error("unknown property for race %s: %s=%s", rc->_name, key, value);
} }
} }

View File

@ -138,7 +138,6 @@ extern "C" {
int df_default; /* Verteidigungsskill Unbewaffnet (default: -2) */ int df_default; /* Verteidigungsskill Unbewaffnet (default: -2) */
int at_bonus; /* Ver<65>ndert den Angriffsskill (default: 0) */ int at_bonus; /* Ver<65>ndert den Angriffsskill (default: 0) */
int df_bonus; /* Ver<65>ndert den Verteidigungskill (default: 0) */ int df_bonus; /* Ver<65>ndert den Verteidigungskill (default: 0) */
struct param *parameters; // additional properties, for an example see natural_armor
struct spellref *precombatspell; struct spellref *precombatspell;
signed char *study_speed; /* study-speed-bonus in points/turn (0=30 Tage) */ signed char *study_speed; /* study-speed-bonus in points/turn (0=30 Tage) */
int flags; int flags;
@ -188,10 +187,13 @@ extern "C" {
void rc_set_param(struct race *rc, const char *key, const char *value); void rc_set_param(struct race *rc, const char *key, const char *value);
int rc_luxury_trade(const struct race *rc);
int rc_herb_trade(const struct race *rc);
double rc_magres(const struct race *rc); double rc_magres(const struct race *rc);
double rc_maxaura(const struct race *rc); double rc_maxaura(const struct race *rc);
int rc_armor_bonus(const struct race *rc); int rc_armor_bonus(const struct race *rc);
int rc_scare(const struct race *rc); int rc_scare(const struct race *rc);
const char * rc_hungerdamage(const race *rc);
const race *rc_otherrace(const race *rc); const race *rc_otherrace(const race *rc);
#define MIGRANTS_NONE 0 #define MIGRANTS_NONE 0

View File

@ -88,9 +88,7 @@ static void test_rc_set_param(CuTest *tc) {
race *rc; race *rc;
test_setup(); test_setup();
rc = test_create_race("human"); rc = test_create_race("human");
CuAssertPtrEquals(tc, NULL, rc->parameters); CuAssertPtrEquals(tc, NULL, rc->options);
rc_set_param(rc, "hodor", "HODOR");
CuAssertStrEquals(tc, "HODOR", get_param(rc->parameters, "hodor"));
rc_set_param(rc, "recruit_multi", "0.5"); rc_set_param(rc, "recruit_multi", "0.5");
CuAssertDblEquals(tc, 0.5, rc->recruit_multi, 0.0); CuAssertDblEquals(tc, 0.5, rc->recruit_multi, 0.0);
rc_set_param(rc, "migrants.formula", "1"); rc_set_param(rc, "migrants.formula", "1");
@ -98,6 +96,8 @@ static void test_rc_set_param(CuTest *tc) {
CuAssertIntEquals(tc, MIGRANTS_LOG10, rc_migrants_formula(rc)); CuAssertIntEquals(tc, MIGRANTS_LOG10, rc_migrants_formula(rc));
rc_set_param(rc, "ai.scare", "400"); rc_set_param(rc, "ai.scare", "400");
CuAssertIntEquals(tc, 400, rc_scare(rc)); CuAssertIntEquals(tc, 400, rc_scare(rc));
rc_set_param(rc, "hunger.damage", "1d10+12");
CuAssertStrEquals(tc, "1d10+12", rc_hungerdamage(rc));
test_cleanup(); test_cleanup();
} }

View File

@ -1738,7 +1738,6 @@ static int parse_races(xmlDocPtr doc)
xmlFree(propValue); xmlFree(propValue);
} }
} }
rc->recruit_multi = get_param_flt(rc->parameters, "recruit_multi", 1.0);
/* reading eressea/races/race/skill */ /* reading eressea/races/race/skill */
xpath->node = node; xpath->node = node;

View File

@ -66,22 +66,6 @@ attrib_type at_market = {
NULL, NULL, NULL, ATF_UNIQUE NULL, NULL, NULL, ATF_UNIQUE
}; };
int rc_luxury_trade(const struct race *rc)
{
if (rc) {
return get_param_int(rc->parameters, "luxury_trade", 1000);
}
return 1000;
}
int rc_herb_trade(const struct race *rc)
{
if (rc) {
return get_param_int(rc->parameters, "herb_trade", 500);
}
return 500;
}
#define MAX_MARKETS 128 #define MAX_MARKETS 128
#define MIN_PEASANTS 50 /* if there are at least this many peasants, you will get 1 good */ #define MIN_PEASANTS 50 /* if there are at least this many peasants, you will get 1 good */

View File

@ -31,10 +31,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <assert.h> #include <assert.h>
static double rc_popularity(const struct race *rc) static double popularity()
{ {
int pop = get_param_int(rc->parameters, "morale", MORALE_AVERAGE); return 1.0 / (MORALE_AVERAGE - MORALE_COOLDOWN); /* 10 turns average */
return 1.0 / (pop - MORALE_COOLDOWN); /* 10 turns average */
} }
void morale_update(region *r) { void morale_update(region *r) {
@ -52,7 +51,7 @@ void morale_update(region *r) {
if (morale < maxmorale) { if (morale < maxmorale) {
if (stability > MORALE_COOLDOWN && r->land->ownership->owner if (stability > MORALE_COOLDOWN && r->land->ownership->owner
&& morale < MORALE_MAX) { && morale < MORALE_MAX) {
double ch = rc_popularity(r->land->ownership->owner->race); double ch = popularity();
if (is_cursed(r->attribs, C_GENEROUS, 0)) { if (is_cursed(r->attribs, C_GENEROUS, 0)) {
ch *= 1.2; /* 20% improvement */ ch *= 1.2; /* 20% improvement */
} }

View File

@ -59,7 +59,7 @@ static void help_feed(unit * donor, unit * u, int *need_p)
} }
static const char *hunger_damage(const race *rc) { static const char *hunger_damage(const race *rc) {
const char * damage = rc->parameters ? get_param(rc->parameters, "hunger.damage") : NULL; const char * damage = rc_hungerdamage(rc);
if (!damage) { if (!damage) {
damage = config_get("hunger.damage"); damage = config_get("hunger.damage");
} }
@ -98,11 +98,11 @@ static bool hunger(int number, unit * u)
deathcounts(r, dead); deathcounts(r, dead);
} }
if (hpsub > 0) { if (hpsub > 0) {
/* Jetzt die Schäden der nicht gestorbenen abziehen. */ /* Jetzt die Sch<EFBFBD>den der nicht gestorbenen abziehen. */
u->hp -= hpsub; u->hp -= hpsub;
/* Meldung nur, wenn noch keine für Tote generiert. */ /* Meldung nur, wenn noch keine f<EFBFBD>r Tote generiert. */
if (dead == 0) { if (dead == 0) {
/* Durch unzureichende Ernährung wird %s geschwächt */ /* Durch unzureichende Ern<EFBFBD>hrung wird %s geschw<68>cht */
ADDMSG(&u->faction->msgs, msg_message("malnourish", "unit region", u, r)); ADDMSG(&u->faction->msgs, msg_message("malnourish", "unit region", u, r));
} }
} }
@ -125,13 +125,13 @@ void get_food(region * r)
return; return;
} }
/* 1. Versorgung von eigenen Einheiten. Das vorhandene Silber /* 1. Versorgung von eigenen Einheiten. Das vorhandene Silber
* wird zunächst so auf die Einheiten aufgeteilt, dass idealerweise * wird zun<EFBFBD>chst so auf die Einheiten aufgeteilt, dass idealerweise
* jede Einheit genug Silber für ihren Unterhalt hat. */ * jede Einheit genug Silber f<EFBFBD>r ihren Unterhalt hat. */
for (u = r->units; u; u = u->next) { for (u = r->units; u; u = u->next) {
int need = lifestyle(u); int need = lifestyle(u);
/* Erstmal zurücksetzen */ /* Erstmal zur<EFBFBD>cksetzen */
freset(u, UFL_HUNGER); freset(u, UFL_HUNGER);
if (u->ship && (u->ship->flags & SF_FISHING)) { if (u->ship && (u->ship->flags & SF_FISHING)) {
@ -230,7 +230,7 @@ void get_food(region * r)
} }
/* 3. bestimmen, wie viele Bauern gefressen werden. /* 3. bestimmen, wie viele Bauern gefressen werden.
* bei fehlenden Bauern den Dämon hungern lassen * bei fehlenden Bauern den D<EFBFBD>mon hungern lassen
*/ */
for (u = r->units; u; u = u->next) { for (u = r->units; u; u = u->next) {
if (u_race(u) == rc_demon) { if (u_race(u) == rc_demon) {
@ -293,7 +293,7 @@ void get_food(region * r)
} }
rsetpeasants(r, peasantfood / 10); rsetpeasants(r, peasantfood / 10);
/* 3. Von den überlebenden das Geld abziehen: */ /* 3. Von den <EFBFBD>berlebenden das Geld abziehen: */
for (u = r->units; u; u = u->next) { for (u = r->units; u; u = u->next) {
int need = MIN(get_money(u), lifestyle(u)); int need = MIN(get_money(u), lifestyle(u));
change_money(u, -need); change_money(u, -need);