optimization: caching resource types in get_resourcetype.

eliminate some it_find calls.
eliminate static variables, they make testing hard.
This commit is contained in:
Enno Rehling 2014-06-24 07:42:45 -07:00
parent 98470ac3c3
commit d581737744
18 changed files with 509 additions and 498 deletions

View File

@ -6879,16 +6879,6 @@
this item, use the CLAIM and SHOW commands).</text>
</string>
<string name="grail">
<text locale="de">Gral</text>
<text locale="en">grail</text>
</string>
<string name="grail_p">
<text locale="de">Grale</text>
<text locale="en">grails</text>
</string>
<string name="studypotion">
<text locale="de">Lerntrank</text>
<text locale="en">brain boost</text>

View File

@ -999,10 +999,12 @@ void add_spende(faction * f1, faction * f2, int amount, region * r)
static bool maintain(building * b, bool first)
/* first==false -> take money from wherever you can */
{
int c;
region *r = b->region;
bool paid = true, work = first;
unit *u;
const resource_type *rsilver = get_resourcetype(R_SILVER);
int c;
region *r = b->region;
bool paid = true, work = first;
unit *u;
if (fval(b, BLD_MAINTAINED) || b->type == NULL || b->type->maintenance == NULL
|| is_cursed(b->attribs, C_NOCOST, 0)) {
fset(b, BLD_MAINTAINED);
@ -1094,7 +1096,7 @@ static bool maintain(building * b, bool first)
continue;
cost -= give;
fset(ua->faction, FFL_SELECT);
if (m->rtype == r_silver)
if (m->rtype == rsilver)
add_spende(ua->faction, u->faction, give, r);
if (cost <= 0)
break;
@ -1818,16 +1820,17 @@ const attrib_type at_luxuries = {
static void expandbuying(region * r, request * buyorders)
{
int max_products;
unit *u;
static struct trade {
const luxury_type *type;
int number;
int multi;
} *trades, *trade;
static int ntrades = 0;
int i, j;
const luxury_type *ltype;
const resource_type *rsilver = get_resourcetype(R_SILVER);
int max_products;
unit *u;
static struct trade {
const luxury_type *type;
int number;
int multi;
} *trades, *trade;
static int ntrades = 0;
int i, j;
const luxury_type *ltype;
if (ntrades == 0) {
for (ltype = luxurytypes; ltype; ltype = ltype->next)
@ -1869,7 +1872,7 @@ static void expandbuying(region * r, request * buyorders)
multi = trade->multi;
price = ltype->price * multi;
if (get_pooled(oa[j].unit, get_resourcetype(R_SILVER), GET_DEFAULT,
if (get_pooled(oa[j].unit, rsilver, GET_DEFAULT,
price) >= price) {
unit *u = oa[j].unit;
item *items;
@ -1886,7 +1889,7 @@ static void expandbuying(region * r, request * buyorders)
i_change(&items, ltype->itype, 1);
a->data.v = items;
i_change(&oa[j].unit->items, ltype->itype, 1);
use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, price);
use_pooled(u, rsilver, GET_DEFAULT, price);
if (u->n < 0)
u->n = 0;
u->n += price;
@ -2371,11 +2374,13 @@ static bool sell(unit * u, request ** sellorders, struct order *ord)
static void expandstealing(region * r, request * stealorders)
{
int i;
const resource_type *rsilver = get_resourcetype(R_SILVER);
int i;
assert(rsilver);
expandorders(r, stealorders);
if (!norders)
return;
expandorders(r, stealorders);
if (!norders) return;
/* Für jede unit in der Region wird Geld geklaut, wenn sie Opfer eines
* Beklauen-Orders ist. Jedes Opfer muß einzeln behandelt werden.
@ -2387,7 +2392,7 @@ static void expandstealing(region * r, request * stealorders)
unit *u = findunitg(oa[i].no, r);
int n = 0;
if (u && u->region == r) {
n = get_pooled(u, r_silver, GET_ALL, INT_MAX);
n = get_pooled(u, rsilver, GET_ALL, INT_MAX);
}
#ifndef GOBLINKILL
if (oa[i].type.goblin) { /* Goblin-Spezialklau */
@ -2409,7 +2414,7 @@ static void expandstealing(region * r, request * stealorders)
}
if (n > 0) {
n = _min(n, oa[i].unit->wants);
use_pooled(u, r_silver, GET_ALL, n);
use_pooled(u, rsilver, GET_ALL, n);
oa[i].unit->n = n;
change_money(oa[i].unit, n);
ADDMSG(&u->faction->msgs, msg_message("stealeffect", "unit region amount",
@ -2424,60 +2429,58 @@ static void expandstealing(region * r, request * stealorders)
/* ------------------------------------------------------------- */
static void plant(region * r, unit * u, int raw)
{
int n, i, skill, planted = 0;
const item_type *itype;
static const resource_type *rt_water = NULL;
if (rt_water == NULL)
rt_water = rt_find("p2");
int n, i, skill, planted = 0;
const item_type *itype;
const resource_type *rt_water = get_resourcetype(R_WATER_OF_LIFE);
assert(rt_water != NULL);
if (!fval(r->terrain, LAND_REGION)) {
return;
}
if (rherbtype(r) == NULL) {
cmistake(u, u->thisorder, 108, MSG_PRODUCE);
return;
}
/* Skill prüfen */
skill = eff_skill(u, SK_HERBALISM, r);
itype = rherbtype(r);
if (skill < 6) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "plant_skills",
"skill minskill product", SK_HERBALISM, 6, itype->rtype, 1));
return;
}
/* Wasser des Lebens prüfen */
if (get_pooled(u, rt_water, GET_DEFAULT, 1) == 0) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "resource_missing", "missing", rt_water));
return;
}
n = get_pooled(u, itype->rtype, GET_DEFAULT, skill * u->number);
/* Kräuter prüfen */
if (n == 0) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "resource_missing", "missing",
itype->rtype));
return;
}
n = _min(skill * u->number, n);
n = _min(raw, n);
/* Für jedes Kraut Talent*10% Erfolgschance. */
for (i = n; i > 0; i--) {
if (rng_int() % 10 < skill)
planted++;
}
produceexp(u, SK_HERBALISM, u->number);
/* Alles ok. Abziehen. */
use_pooled(u, rt_water, GET_DEFAULT, 1);
use_pooled(u, itype->rtype, GET_DEFAULT, n);
rsetherbs(r, rherbs(r) + planted);
ADDMSG(&u->faction->msgs, msg_message("plant", "unit region amount herb",
u, r, planted, itype->rtype));
assert(rt_water != NULL);
if (!fval(r->terrain, LAND_REGION)) {
return;
}
if (rherbtype(r) == NULL) {
cmistake(u, u->thisorder, 108, MSG_PRODUCE);
return;
}
/* Skill prüfen */
skill = eff_skill(u, SK_HERBALISM, r);
itype = rherbtype(r);
if (skill < 6) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "plant_skills",
"skill minskill product", SK_HERBALISM, 6, itype->rtype, 1));
return;
}
/* Wasser des Lebens prüfen */
if (get_pooled(u, rt_water, GET_DEFAULT, 1) == 0) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "resource_missing", "missing", rt_water));
return;
}
n = get_pooled(u, itype->rtype, GET_DEFAULT, skill * u->number);
/* Kräuter prüfen */
if (n == 0) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "resource_missing", "missing",
itype->rtype));
return;
}
n = _min(skill * u->number, n);
n = _min(raw, n);
/* Für jedes Kraut Talent*10% Erfolgschance. */
for (i = n; i > 0; i--) {
if (rng_int() % 10 < skill)
planted++;
}
produceexp(u, SK_HERBALISM, u->number);
/* Alles ok. Abziehen. */
use_pooled(u, rt_water, GET_DEFAULT, 1);
use_pooled(u, itype->rtype, GET_DEFAULT, n);
rsetherbs(r, rherbs(r) + planted);
ADDMSG(&u->faction->msgs, msg_message("plant", "unit region amount herb",
u, r, planted, itype->rtype));
}
static void planttrees(region * r, unit * u, int raw)
@ -2607,22 +2610,24 @@ static void breedhorses(region * r, unit * u)
int n, c, breed = 0;
struct building *b = inside_building(u);
const struct building_type *btype = b ? b->type : NULL;
const struct item_type *ihorse = it_find("horse");
assert(ihorse);
const struct resource_type *rhorse = get_resourcetype(R_HORSE);
int horses;
assert(rhorse && rhorse->itype);
if (btype != bt_find("stables")) {
cmistake(u, u->thisorder, 122, MSG_PRODUCE);
return;
}
if (i_get(u->items, ihorse) < 2) {
horses = i_get(u->items, rhorse->itype);
if (horses < 2) {
cmistake(u, u->thisorder, 107, MSG_PRODUCE);
return;
}
n = _min(u->number * eff_skill(u, SK_HORSE_TRAINING, r), i_get(u->items, ihorse));
n = u->number * eff_skill(u, SK_HORSE_TRAINING, r);
n = _min(n, horses);
for (c = 0; c < n; c++) {
if (rng_int() % 100 < eff_skill(u, SK_HORSE_TRAINING, r)) {
i_change(&u->items, ihorse, 1);
i_change(&u->items, rhorse->itype, 1);
++breed;
}
}

View File

@ -89,7 +89,7 @@ add_give(unit * u, unit * u2, int given, int received,
static bool limited_give(const item_type * type)
{
/* trade only money 2:1, if at all */
return (type == i_silver);
return (type->rtype == get_resourcetype(R_SILVER));
}
int give_quota(const unit * src, const unit * dst, const item_type * type,
@ -426,7 +426,7 @@ void give_unit(unit * u, unit * u2, order * ord)
cmistake(u, ord, 156, MSG_COMMERCE);
return;
}
add_give(u, u2, 1, 1, r_unit, ord, 0);
add_give(u, u2, 1, 1, get_resourcetype(R_UNIT), ord, 0);
u_setfaction(u, u2->faction);
u2->faction->newbies += n;
}

View File

@ -88,79 +88,78 @@ static bool
attack_catapult(const troop * at, const struct weapon_type *wtype,
int *casualties)
{
fighter *af = at->fighter;
unit *au = af->unit;
battle *b = af->side->battle;
troop dt;
int d = 0, enemies;
weapon *wp = af->person[at->index].missile;
static item_type *it_catapultammo = NULL;
if (it_catapultammo == NULL) {
fighter *af = at->fighter;
unit *au = af->unit;
battle *b = af->side->battle;
troop dt;
int d = 0, enemies;
weapon *wp = af->person[at->index].missile;
item_type *it_catapultammo = NULL;
assert(wp->type == wtype);
assert(af->person[at->index].reload == 0);
it_catapultammo = it_find("catapultammo");
}
assert(wp->type == wtype);
assert(af->person[at->index].reload == 0);
if (it_catapultammo != NULL) {
if (get_pooled(au, it_catapultammo->rtype,
GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, 1) <= 0) {
/* No ammo. Use other weapon if available. */
return true;
if (it_catapultammo != NULL) {
if (get_pooled(au, it_catapultammo->rtype,
GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, 1) <= 0) {
/* No ammo. Use other weapon if available. */
return true;
}
}
}
enemies = count_enemies(b, af, FIGHT_ROW, FIGHT_ROW, SELECT_ADVANCE);
enemies = _min(enemies, CATAPULT_ATTACKS);
if (enemies == 0) {
return true; /* allow further attacks */
}
if (af->catmsg == -1) {
int i, k = 0;
message *msg;
for (i = 0; i <= at->index; ++i) {
if (af->person[i].reload == 0 && af->person[i].missile == wp)
++k;
enemies = count_enemies(b, af, FIGHT_ROW, FIGHT_ROW, SELECT_ADVANCE);
enemies = _min(enemies, CATAPULT_ATTACKS);
if (enemies == 0) {
return true; /* allow further attacks */
}
msg = msg_message("battle::usecatapult", "amount unit", k, au);
message_all(b, msg);
msg_release(msg);
af->catmsg = 0;
}
if (it_catapultammo != NULL) {
use_pooled(au, it_catapultammo->rtype,
GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, 1);
}
while (--enemies >= 0) {
/* Select defender */
dt = select_enemy(af, FIGHT_ROW, FIGHT_ROW, SELECT_ADVANCE);
if (!dt.fighter)
break;
/* If battle succeeds */
if (hits(*at, dt, wp)) {
d += terminate(dt, *at, AT_STANDARD, wp->type->damage[0], true);
if (af->catmsg == -1) {
int i, k = 0;
message *msg;
for (i = 0; i <= at->index; ++i) {
if (af->person[i].reload == 0 && af->person[i].missile == wp)
++k;
}
msg = msg_message("battle::usecatapult", "amount unit", k, au);
message_all(b, msg);
msg_release(msg);
af->catmsg = 0;
}
if (it_catapultammo != NULL) {
use_pooled(au, it_catapultammo->rtype,
GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, 1);
}
while (--enemies >= 0) {
/* Select defender */
dt = select_enemy(af, FIGHT_ROW, FIGHT_ROW, SELECT_ADVANCE);
if (!dt.fighter)
break;
/* If battle succeeds */
if (hits(*at, dt, wp)) {
d += terminate(dt, *at, AT_STANDARD, wp->type->damage[0], true);
#ifdef CATAPULT_STRUCTURAL_DAMAGE
if (dt.fighter->unit->building && rng_int() % 100 < 5) {
float dmg =
get_param_flt(global.parameters, "rules.building.damage.catapult", 1);
damage_building(b, dt.fighter->unit->building, dmg);
} else if (dt.fighter->unit->ship && rng_int() % 100 < 5) {
float dmg =
get_param_flt(global.parameters, "rules.ship.damage.catapult", 0.01);
damage_ship(dt.fighter->unit->ship, dmg)
}
if (dt.fighter->unit->building && rng_int() % 100 < 5) {
float dmg =
get_param_flt(global.parameters, "rules.building.damage.catapult", 1);
damage_building(b, dt.fighter->unit->building, dmg);
} else if (dt.fighter->unit->ship && rng_int() % 100 < 5) {
float dmg =
get_param_flt(global.parameters, "rules.ship.damage.catapult", 0.01);
damage_ship(dt.fighter->unit->ship, dmg)
}
#endif
}
}
}
if (casualties)
*casualties = d;
return false; /* keine weitren attacken */
if (casualties) {
*casualties = d;
}
return false; /* keine weitren attacken */
}
void register_weapons(void)

View File

@ -2314,40 +2314,35 @@ static void add_tactics(tactics * ta, fighter * fig, int value)
static double horsebonus(const unit * u)
{
static const item_type *it_horse = 0;
static const item_type *it_elvenhorse = 0;
static const item_type *it_charger = 0;
region *r = u->region;
int n1 = 0, n2 = 0, n3 = 0;
item *itm = u->items;
int skl = eff_skill(u, SK_RIDING, r);
const item_type *it_horse, *it_elvenhorse, *it_charger;
int n1 = 0, n2 = 0, n3 = 0;
item *itm;
int skl = eff_skill(u, SK_RIDING, u->region);
const resource_type *rtype;
if (skl < 1) return 0.0;
it_horse = (rtype = get_resourcetype(R_HORSE)) ? rtype->itype : 0;
it_elvenhorse = (rtype = get_resourcetype(R_UNICORN)) ? rtype->itype : 0;
it_charger = (rtype = get_resourcetype(R_CHARGER)) ? rtype->itype : 0;
if (skl < 1)
return 0.0;
if (it_horse == 0) {
it_horse = it_find("horse");
it_elvenhorse = it_find("elvenhorse");
it_charger = it_find("charger");
}
for (; itm; itm = itm->next) {
if (itm->type->flags & ITF_ANIMAL) {
if (itm->type == it_elvenhorse)
n3 += itm->number;
else if (itm->type == it_charger)
n2 += itm->number;
else if (itm->type == it_horse)
n1 += itm->number;
for (itm=u->items; itm; itm = itm->next) {
if (itm->type->flags & ITF_ANIMAL) {
if (itm->type == it_elvenhorse)
n3 += itm->number;
else if (itm->type == it_charger)
n2 += itm->number;
else if (itm->type == it_horse)
n1 += itm->number;
}
}
}
if (skl >= 5 && n3 >= u->number)
return 0.30;
if (skl >= 3 && n2 + n3 >= u->number)
return 0.20;
if (skl >= 1 && n1 + n2 + n3 >= u->number)
return 0.10;
return 0.0F;
if (skl >= 5 && n3 >= u->number)
return 0.30;
if (skl >= 3 && n2 + n3 >= u->number)
return 0.20;
if (skl >= 1 && n1 + n2 + n3 >= u->number)
return 0.10;
return 0.0F;
}
double fleechance(unit * u)

View File

@ -830,15 +830,8 @@ cansee(const faction * f, const region * r, const unit * u, int modifier)
/* und es muss niemand aus f in der region sein, wenn sie vom Turm
* erblickt wird */
{
int stealth, rings;
unit *u2 = r->units;
static const item_type *itype_grail;
static bool init;
if (!init) {
init = true;
itype_grail = it_find("grail");
}
int stealth, rings;
unit *u2 = r->units;
if (u->faction == f || omniscient(f)) {
return true;
@ -856,8 +849,6 @@ cansee(const faction * f, const region * r, const unit * u, int modifier)
if (leftship(u))
return true;
if (itype_grail != NULL && i_get(u->items, itype_grail))
return true;
while (u2 && u2->faction != f)
u2 = u2->next;

View File

@ -190,22 +190,24 @@ void it_register(item_type * itype)
item_type *new_itemtype(resource_type * rtype,
int iflags, int weight, int capacity)
{
item_type *itype;
assert(resource2item(rtype) == NULL);
assert(rtype->flags & RTF_ITEM);
item_type *itype;
itype = calloc(sizeof(item_type), 1);
itype->rtype = rtype;
rtype->itype = itype;
itype->weight = weight;
itype->capacity = capacity;
itype->flags |= iflags;
it_register(itype);
rtype->uchange = res_changeitem;
return itype;
assert(!rtype->itype);
assert(!rtype->uchange || rtype->uchange==res_changeitem);
itype = calloc(sizeof(item_type), 1);
itype->rtype = rtype;
itype->weight = weight;
itype->capacity = capacity;
itype->flags |= iflags;
it_register(itype);
rtype->itype = itype;
rtype->flags |= RTF_ITEM;
rtype->uchange = res_changeitem;
return itype;
}
static void lt_register(luxury_type * ltype)
@ -295,15 +297,18 @@ potion_type *new_potiontype(item_type * itype, int level)
return ptype;
}
static int num_resources;
void rt_register(resource_type * rtype)
{
char buffer[64];
const char * name = rtype->_name[0];
size_t len = strlen(name);
assert(len<sizeof(buffer)-sizeof(rtype));
len = cb_new_kv(name, len, &rtype, sizeof(rtype), buffer);
cb_insert(&cb_resources, buffer, len);
char buffer[64];
const char * name = rtype->_name[0];
size_t len = strlen(name);
assert(len<sizeof(buffer)-sizeof(rtype));
len = cb_new_kv(name, len, &rtype, sizeof(rtype), buffer);
cb_insert(&cb_resources, buffer, len);
++num_resources;
}
const resource_type *item2resource(const item_type * itype)
@ -602,13 +607,23 @@ const char *itemnames[MAX_RESOURCES] = {
"iron", "stone", "horse", "ao_healing",
"aots", "roi", "rop", "ao_chastity",
"laen", "fairyboot", "aoc", "pegasus",
"elvenhorse", "dolphin", "roqf", "trollbelt",
"elvenhorse", "charger", "dolphin", "roqf", "trollbelt",
"aurafocus", "sphereofinv", "magicbag",
"magicherbbag", "dreameye", "money", "aura", "permaura"
"magicherbbag", "dreameye", "p2", "money", "aura", "permaura",
"hp", "unit", "peasant"
};
const resource_type *get_resourcetype(resource_t type) {
const resource_type *rtype = rt_find(itemnames[type]);
static int update;
static const struct resource_type *rtypes[MAX_RESOURCES];
if (update!=num_resources) {
memset(rtypes, 0, sizeof(rtypes));
update = num_resources;
}
const resource_type *rtype = rtypes[type];
if (!rtype) {
rtype = rtypes[type] = rt_find(itemnames[type]);
}
return rtype;
}
@ -932,14 +947,6 @@ static void init_oldpotions(void)
}
}
resource_type *r_silver;
resource_type *r_aura;
resource_type *r_permaura;
resource_type *r_unit;
static resource_type *r_hp;
item_type *i_silver;
static const char *names[] = {
"money", "money_p",
"person", "person_p",
@ -953,89 +960,118 @@ static const char *names[] = {
void init_resources(void)
{
resource_type *rtype;
if (r_hp) {
// we have done this already
return;
item_type *itype;
rtype = rt_find(names[8]);
if (!rtype) {
rtype = new_resourcetype(names + 8, NULL, RTF_NONE);
rt_register(rtype);
}
rtype->uchange = res_changepeasants;
// R_SILVER
rtype = rt_find(names[0]);
if (!rtype) {
rtype = new_resourcetype(&names[0], NULL, RTF_ITEM | RTF_POOLED);
rt_register(rtype);
}
rtype->uchange = res_changeitem;
itype = rtype->itype;
if (!itype) {
itype = new_itemtype(rtype, ITF_NONE, 1 /*weight */ , 0);
}
itype->give = give_money;
rtype = new_resourcetype(names + 8, NULL, RTF_NONE);
rtype->uchange = res_changepeasants;
rt_register(rtype);
// R_PERMAURA
rtype = rt_find(names[4]);
if (!rtype) {
rtype = new_resourcetype(&names[4], NULL, RTF_NONE);
rt_register(rtype);
}
rtype->uchange = res_changepermaura;
// R_LIFE
rtype = rt_find(names[6]);
if (!rtype) {
rtype = new_resourcetype(&names[6], NULL, RTF_NONE);
rt_register(rtype);
}
rtype->uchange = res_changehp;
// R_AURA
rtype = rt_find(names[10]);
if (!rtype) {
rtype = new_resourcetype(&names[10], NULL, RTF_NONE);
rt_register(rtype);
}
rtype->uchange = res_changeaura;
r_silver = new_resourcetype(&names[0], NULL, RTF_ITEM | RTF_POOLED);
i_silver = new_itemtype(r_silver, ITF_NONE, 1 /*weight */ , 0);
r_silver->uchange = res_changeitem;
i_silver->give = give_money;
rt_register(r_silver);
r_permaura = new_resourcetype(&names[4], NULL, RTF_NONE);
r_permaura->uchange = res_changepermaura;
rt_register(r_permaura);
r_hp = new_resourcetype(&names[6], NULL, RTF_NONE);
r_hp->uchange = res_changehp;
rt_register(r_hp);
r_aura = new_resourcetype(&names[10], NULL, RTF_NONE);
r_aura->uchange = res_changeaura;
rt_register(r_aura);
r_unit = new_resourcetype(&names[12], NULL, RTF_NONE);
r_unit->uchange = res_changeperson;
rt_register(r_unit);
/* alte typen registrieren: */
init_oldpotions();
// R_UNIT
rtype = rt_find(names[12]);
if (!rtype) {
rtype = new_resourcetype(&names[12], NULL, RTF_NONE);
rt_register(rtype);
}
rtype->uchange = res_changeperson;
/* alte typen registrieren: */
init_oldpotions();
}
int get_money(const unit * u)
{
const item *i = u->items;
while (i && i->type != i_silver)
i = i->next;
if (i == NULL)
return 0;
return i->number;
const struct resource_type *rtype = get_resourcetype(R_SILVER);
const item *i = u->items;
while (i && i->type->rtype != rtype) {
i = i->next;
}
return i ? i->number : 0;
}
int set_money(unit * u, int v)
{
item **ip = &u->items;
while (*ip && (*ip)->type != i_silver)
ip = &(*ip)->next;
if ((*ip) == NULL && v) {
i_add(&u->items, i_new(i_silver, v));
const struct resource_type *rtype = get_resourcetype(R_SILVER);
item **ip = &u->items;
while (*ip && (*ip)->type->rtype != rtype) {
ip = &(*ip)->next;
}
if ((*ip) == NULL && v) {
i_add(&u->items, i_new(rtype->itype, v));
return v;
}
if ((*ip) != NULL) {
if (v) {
(*ip)->number = v;
assert((*ip)->number >= 0);
} else {
i_remove(ip, *ip);
}
}
return v;
}
if ((*ip) != NULL) {
if (v) {
(*ip)->number = v;
assert((*ip)->number >= 0);
} else
i_remove(ip, *ip);
}
return v;
}
int change_money(unit * u, int v)
{
item **ip = &u->items;
while (*ip && (*ip)->type != i_silver)
ip = &(*ip)->next;
if ((*ip) == NULL && v) {
i_add(&u->items, i_new(i_silver, v));
return v;
}
if ((*ip) != NULL) {
item *i = *ip;
if (i->number + v != 0) {
i->number += v;
assert(i->number >= 0);
return i->number;
} else
i_free(i_remove(ip, *ip));
}
return 0;
const struct resource_type *rtype = get_resourcetype(R_SILVER);
item **ip = &u->items;
while (*ip && (*ip)->type->rtype != rtype) {
ip = &(*ip)->next;
}
if ((*ip) == NULL && v) {
i_add(&u->items, i_new(rtype->itype, v));
return v;
}
if ((*ip) != NULL) {
item *i = *ip;
if (i->number + v != 0) {
i->number += v;
assert(i->number >= 0);
return i->number;
} else {
i_free(i_remove(ip, *ip));
}
}
return 0;
}
static int add_resourcename_cb(const void * match, const void * key, size_t keylen, void *data)
@ -1187,21 +1223,19 @@ int free_rtype_cb(const void * match, const void * key, size_t keylen, void *cbd
void test_clear_resources(void)
{
int i;
int i;
memset((void *)oldpotiontype, 0, sizeof(oldpotiontype));
cb_foreach(&cb_items, "", 0, free_itype_cb, 0);
cb_clear(&cb_items);
cb_foreach(&cb_resources, "", 0, free_rtype_cb, 0);
cb_clear(&cb_resources);
r_hp = r_silver = r_aura = r_permaura = r_unit = 0;
i_silver = 0;
for (i=0; i!=MAXLOCALES; ++i) {
cb_clear(inames+i);
}
memset((void *)oldpotiontype, 0, sizeof(oldpotiontype));
cb_foreach(&cb_items, "", 0, free_itype_cb, 0);
cb_clear(&cb_items);
cb_foreach(&cb_resources, "", 0, free_rtype_cb, 0);
cb_clear(&cb_resources);
++num_resources;
for (i=0; i!=MAXLOCALES; ++i) {
cb_clear(inames+i);
}
}
#endif

View File

@ -265,20 +265,12 @@ extern "C" {
double magres, int prot, unsigned int flags);
extern potion_type *new_potiontype(item_type * itype, int level);
/* for lack of another file: */
/* sonstige resourcen */
extern resource_type *r_silver;
extern resource_type *r_aura;
extern resource_type *r_permaura;
extern resource_type *r_unit;
typedef enum {
/* ITEMS: */
R_IRON,
R_STONE,
R_HORSE,
/**/ R_AMULET_OF_HEALING,
R_AMULET_OF_HEALING,
R_AMULET_OF_TRUE_SEEING,
R_RING_OF_INVISIBILITY,
R_RING_OF_POWER,
@ -288,6 +280,7 @@ extern "C" {
R_BIRTHDAYAMULET,
R_PEGASUS,
R_UNICORN,
R_CHARGER,
R_DOLPHIN,
R_RING_OF_NIMBLEFINGER,
R_TROLLBELT,
@ -296,11 +289,15 @@ extern "C" {
R_BAG_OF_HOLDING,
R_SACK_OF_CONSERVATION,
R_TACTICCRYSTAL,
R_WATER_OF_LIFE,
/* SONSTIGE */
R_SILVER,
R_AURA, /* Aura */
R_PERMAURA, /* Permanente Aura */
R_LIFE,
R_UNIT,
R_PEASANT,
MAX_RESOURCES, /* do not use outside item.c ! */
NORESOURCE = -1
@ -326,8 +323,6 @@ extern "C" {
extern void register_item_useonother(int (*foo) (struct unit *, int,
const struct item_type *, int, struct order *), const char *name);
extern struct item_type *i_silver;
#ifndef DISABLE_TESTS
void test_clear_resources(void);
#endif

View File

@ -45,7 +45,7 @@ void test_change_person(CuTest * tc)
test_create_world();
u = test_create_unit(0, 0);
test_uchange(tc, u, r_unit);
test_uchange(tc, u, get_resourcetype(R_UNIT));
}
void test_resource_type(CuTest * tc)

View File

@ -777,8 +777,9 @@ int countspells(unit * u, int step)
*/
int spellcost(unit * u, const spell * sp)
{
int k, aura = 0;
int count = countspells(u, 0);
int k, aura = 0;
int count = countspells(u, 0);
const resource_type *r_aura = get_resourcetype(R_AURA);
for (k = 0; sp->components[k].type; k++) {
if (sp->components[k].type == r_aura) {
@ -826,8 +827,9 @@ static int spl_costtyp(const spell * sp)
* */
int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range)
{
int k, maxlevel, needplevel;
int costtyp = SPC_FIX;
const resource_type *r_aura = get_resourcetype(R_AURA);
int k, maxlevel, needplevel;
int costtyp = SPC_FIX;
for (k = 0; sp->components[k].type; k++) {
if (cast_level == 0)
@ -888,8 +890,9 @@ int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range)
*/
void pay_spell(unit * u, const spell * sp, int cast_level, int range)
{
int k;
int resuse;
const resource_type *r_aura = get_resourcetype(R_AURA);
int k;
int resuse;
assert(cast_level>0);
for (k = 0; sp->components[k].type; k++) {
@ -934,9 +937,10 @@ bool knowsspell(const region * r, const unit * u, const spell * sp)
bool
cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
{
int k;
int itemanz;
resource *reslist = NULL;
const resource_type *r_aura = get_resourcetype(R_AURA);
int k;
int itemanz;
resource *reslist = NULL;
if (!knowsspell(u->region, u, sp)) {
/* Diesen Zauber kennt die Einheit nicht */

View File

@ -412,18 +412,15 @@ bool canswim(unit * u)
static int canride(unit * u)
{
int horses = 0, maxhorses, unicorns = 0, maxunicorns;
int skill = effskill(u, SK_RIDING);
item *itm;
static const item_type *it_horse = 0;
static const item_type *it_elvenhorse = 0;
static const item_type *it_charger = 0;
int horses = 0, maxhorses, unicorns = 0, maxunicorns;
int skill = effskill(u, SK_RIDING);
item *itm;
const item_type *it_horse, *it_elvenhorse, *it_charger;
const resource_type *rtype;
if (it_horse == 0) {
it_horse = it_find("horse");
it_elvenhorse = it_find("elvenhorse");
it_charger = it_find("charger");
}
it_horse = (rtype = get_resourcetype(R_HORSE)) ? rtype->itype : 0;
it_elvenhorse = (rtype = get_resourcetype(R_UNICORN)) ? rtype->itype : 0;
it_charger = (rtype = get_resourcetype(R_CHARGER)) ? rtype->itype : 0;
for (itm = u->items; itm; itm = itm->next) {
if (itm->type == it_horse || itm->type == it_charger) {
@ -839,26 +836,26 @@ static void caught_target(region * r, unit * u)
static unit *bewegung_blockiert_von(unit * reisender, region * r)
{
unit *u;
double prob = 0.0;
bool contact = false;
unit *guard = NULL;
int stealth = eff_stealth(reisender, r);
static int gamecookie = -1;
static double base_prob = -999;
static double skill_prob = -999;
static double amulet_prob = -999;
const struct item_type *iamulet = it_find("aots");
unit *u;
double prob = 0.0;
bool contact = false;
unit *guard = NULL;
int stealth = eff_stealth(reisender, r);
static int gamecookie = -1;
static double base_prob = -999;
static double skill_prob = -999;
static double amulet_prob = -999;
const struct resource_type *ramulet = get_resourcetype(R_AMULET_OF_TRUE_SEEING);
if (gamecookie < 0 || gamecookie != global.cookie) {
base_prob =
get_param_flt(global.parameters, "rules.guard.base_stop_prob", .3);
skill_prob =
get_param_flt(global.parameters, "rules.guard.skill_stop_prob", .1);
amulet_prob =
get_param_flt(global.parameters, "rules.guard.amulet_stop_prob", .1);
gamecookie = global.cookie;
}
if (gamecookie < 0 || gamecookie != global.cookie) {
base_prob =
get_param_flt(global.parameters, "rules.guard.base_stop_prob", .3);
skill_prob =
get_param_flt(global.parameters, "rules.guard.skill_stop_prob", .1);
amulet_prob =
get_param_flt(global.parameters, "rules.guard.amulet_stop_prob", .1);
gamecookie = global.cookie;
}
if (fval(u_race(reisender), RCF_ILLUSIONARY))
return NULL;
@ -876,7 +873,7 @@ static unit *bewegung_blockiert_von(unit * reisender, region * r)
else if (sk >= stealth) {
double prob_u = (sk - stealth) * skill_prob;
/* amulet counts at most once */
prob_u += _min (1, _min(u->number, i_get(u->items, iamulet))) * amulet_prob;
prob_u += _min (1, _min(u->number, i_get(u->items, ramulet->itype))) * amulet_prob;
if (prob_u >= prob) {
prob = prob_u;
guard = u;

View File

@ -1015,11 +1015,11 @@ void region_setresource(region * r, const resource_type * rtype, int value)
rm = rm->next;
}
if (!rm) {
if (rtype == rt_find("money"))
if (rtype == get_resourcetype(R_SILVER))
rsetmoney(r, value);
else if (rtype == rt_find("peasant"))
else if (rtype == get_resourcetype(R_PEASANT))
rsetpeasants(r, value);
else if (rtype == rt_find("horse"))
else if (rtype == get_resourcetype(R_HORSE))
rsethorses(r, value);
else {
int i;
@ -1042,11 +1042,11 @@ int region_getresource(const region * r, const resource_type * rtype)
return rm->amount;
}
}
if (rtype == rt_find("money"))
if (rtype == get_resourcetype(R_SILVER))
return rmoney(r);
if (rtype == rt_find("horse"))
if (rtype == get_resourcetype(R_HORSE))
return rhorses(r);
if (rtype == rt_find("peasant"))
if (rtype == get_resourcetype(R_PEASANT))
return rpeasants(r);
return 0;
}

View File

@ -140,7 +140,9 @@ void
report_item(const unit * owner, const item * i, const faction * viewer,
const char **name, const char **basename, int *number, bool singular)
{
assert(!owner || owner->number);
const resource_type *rsilver = get_resourcetype(R_SILVER);
assert(!owner || owner->number);
if (owner && owner->faction == viewer) {
if (name)
*name =
@ -150,7 +152,7 @@ report_item(const unit * owner, const item * i, const faction * viewer,
*basename = resourcename(i->type->rtype, 0);
if (number)
*number = i->number;
} else if (owner && i->type->rtype == r_silver) {
} else if (owner && i->type->rtype == rsilver) {
int pp = i->number / owner->number;
if (number)
*number = 1;

View File

@ -220,28 +220,29 @@ static buddy *get_friends(const unit * u, int *numfriends)
*/
int gift_items(unit * u, int flags)
{
region *r = u->region;
item **itm_p = &u->items;
int retval = 0;
int rule = rule_give();
const struct resource_type *rsilver = get_resourcetype(R_SILVER);
region *r = u->region;
item **itm_p = &u->items;
int retval = 0;
int rule = rule_give();
assert(u->region);
assert(u->faction);
assert(u->region);
assert(u->faction);
if ((u->faction->flags & FFL_QUIT) == 0 || (rule & GIVE_ONDEATH) == 0) {
if ((rule & GIVE_ALLITEMS) == 0 && (flags & GIFT_FRIENDS))
flags -= GIFT_FRIENDS;
if ((rule & GIVE_PEASANTS) == 0 && (flags & GIFT_PEASANTS))
flags -= GIFT_PEASANTS;
if ((rule & GIVE_SELF) == 0 && (flags & GIFT_SELF))
flags -= GIFT_SELF;
}
if (u->items == NULL || fval(u_race(u), RCF_ILLUSIONARY))
return 0;
if ((u_race(u)->ec_flags & GIVEITEM) == 0)
return 0;
if ((u->faction->flags & FFL_QUIT) == 0 || (rule & GIVE_ONDEATH) == 0) {
if ((rule & GIVE_ALLITEMS) == 0 && (flags & GIFT_FRIENDS))
flags -= GIFT_FRIENDS;
if ((rule & GIVE_PEASANTS) == 0 && (flags & GIFT_PEASANTS))
flags -= GIFT_PEASANTS;
if ((rule & GIVE_SELF) == 0 && (flags & GIFT_SELF))
flags -= GIFT_SELF;
}
if (u->items == NULL || fval(u_race(u), RCF_ILLUSIONARY))
return 0;
if ((u_race(u)->ec_flags & GIVEITEM) == 0)
return 0;
/* at first, I should try giving my crap to my own units in this region */
if (u->faction && (u->faction->flags & FFL_QUIT) == 0 && (flags & GIFT_SELF)) {
unit *u2, *u3 = NULL;
@ -303,7 +304,7 @@ int gift_items(unit * u, int flags)
if (flags & GIFT_PEASANTS) {
if (!fval(u->region->terrain, SEA_REGION)) {
if (itm->type == i_silver) {
if (itm->type->rtype == rsilver) {
rsetmoney(r, rmoney(r) + itm->number);
itm->number = 0;
}
@ -1220,13 +1221,14 @@ static int item_modification(const unit * u, skill_t sk, int val)
#endif
}
#if NEWATSROI == 1
if (sk == SK_PERCEPTION) {
if (i_get(u->items, it_find("aots")) >= u->number) {
val += ATSBONUS;
if (sk == SK_PERCEPTION) {
const struct resource_type *rtype = get_resourcetype(R_AMULET_OF_TRUE_SEEING);
if (i_get(u->items, rtype->itype) >= u->number) {
val += ATSBONUS;
}
}
}
#endif
return val;
return val;
}
static int att_modification(const unit * u, skill_t sk)

View File

@ -292,13 +292,12 @@ void get_food(region * r)
int hungry = u->number;
/* use peasantblood before eating the peasants themselves */
static const struct potion_type *pt_blood;
if (pt_blood == NULL) {
const item_type *it_blood = it_find("peasantblood");
if (it_blood)
const struct potion_type *pt_blood = 0;
const item_type *it_blood = it_find("peasantblood");
if (it_blood) {
pt_blood = it_blood->rtype->ptype;
}
if (pt_blood != NULL) {
if (pt_blood) {
/* always start with the unit itself, then the first known unit that may have some blood */
unit *donor = u;
while (donor != NULL && hungry > 0) {
@ -2694,6 +2693,7 @@ static void reshow(unit * u, struct order *ord, const char *s, param_t p)
int promotion_cmd(unit * u, struct order *ord)
{
const struct resource_type *rsilver = get_resourcetype(R_SILVER);
int money, people;
if (fval(u, UFL_HERO)) {
@ -2713,14 +2713,14 @@ int promotion_cmd(unit * u, struct order *ord)
return 0;
}
people = count_all(u->faction) * u->number;
money = get_pooled(u, i_silver->rtype, GET_ALL, people);
money = get_pooled(u, rsilver, GET_ALL, people);
if (people > money) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, ord, "heroes_cost", "cost have", people, money));
return 0;
}
use_pooled(u, i_silver->rtype, GET_ALL, people);
use_pooled(u, rsilver, GET_ALL, people);
fset(u, UFL_HERO);
ADDMSG(&u->faction->msgs, msg_message("hero_promotion", "unit cost",
u, people));
@ -4327,86 +4327,82 @@ void process(void)
int siege_cmd(unit * u, order * ord)
{
region *r = u->region;
building *b;
int d, pooled;
int bewaffnete, katapultiere = 0;
static bool init = false;
static const curse_type *magicwalls_ct;
static item_type *it_catapultammo = NULL;
static item_type *it_catapult = NULL;
if (!init) {
init = true;
region *r = u->region;
building *b;
int d, pooled;
int bewaffnete, katapultiere = 0;
const curse_type *magicwalls_ct;
item_type *it_catapultammo = NULL;
item_type *it_catapult = NULL;
init_tokens(ord);
skip_token();
b = getbuilding(r);
if (!b) {
cmistake(u, ord, 31, MSG_BATTLE);
return 31;
}
if (!playerrace(u_race(u))) {
/* keine Drachen, Illusionen, Untote etc */
cmistake(u, ord, 166, MSG_BATTLE);
return 166;
}
/* schaden durch katapulte */
magicwalls_ct = ct_find("magicwalls");
it_catapultammo = it_find("catapultammo");
it_catapult = it_find("catapult");
}
/* gibt es ueberhaupt Burgen? */
init_tokens(ord);
skip_token();
b = getbuilding(r);
if (!b) {
cmistake(u, ord, 31, MSG_BATTLE);
return 31;
}
if (!playerrace(u_race(u))) {
/* keine Drachen, Illusionen, Untote etc */
cmistake(u, ord, 166, MSG_BATTLE);
return 166;
}
/* schaden durch katapulte */
d = i_get(u->items, it_catapult);
d = _min(u->number, d);
pooled = get_pooled(u, it_catapultammo->rtype, GET_DEFAULT, d);
d = _min(pooled, d);
if (eff_skill(u, SK_CATAPULT, r) >= 1) {
katapultiere = d;
d *= eff_skill(u, SK_CATAPULT, r);
} else {
d = 0;
}
bewaffnete = armedmen(u, true);
if (d == 0 && bewaffnete == 0) {
/* abbruch, falls unbewaffnet oder unfaehig, katapulte zu benutzen */
cmistake(u, ord, 80, MSG_EVENT);
return 80;
}
if (!is_guard(u, GUARD_TRAVELTHRU)) {
/* abbruch, wenn die einheit nicht vorher die region bewacht - als
* warnung fuer alle anderen! */
cmistake(u, ord, 81, MSG_EVENT);
return 81;
}
/* einheit und burg markieren - spart zeit beim behandeln der einheiten
* in der burg, falls die burg auch markiert ist und nicht alle
* einheiten wieder abgesucht werden muessen! */
usetsiege(u, b);
b->besieged += _max(bewaffnete, katapultiere);
/* definitiver schaden eingeschraenkt */
d = _min(d, b->size - 1);
/* meldung, schaden anrichten */
if (d && !curse_active(get_curse(b->attribs, magicwalls_ct))) {
b->size -= d;
use_pooled(u, it_catapultammo->rtype,
GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, d);
/* send message to the entire region */
ADDMSG(&r->msgs, msg_message("siege_catapults",
"unit building destruction", u, b, d));
} else {
/* send message to the entire region */
ADDMSG(&r->msgs, msg_message("siege", "unit building", u, b));
}
return 0;
d = i_get(u->items, it_catapult);
d = _min(u->number, d);
pooled = get_pooled(u, it_catapultammo->rtype, GET_DEFAULT, d);
d = _min(pooled, d);
if (eff_skill(u, SK_CATAPULT, r) >= 1) {
katapultiere = d;
d *= eff_skill(u, SK_CATAPULT, r);
} else {
d = 0;
}
bewaffnete = armedmen(u, true);
if (d == 0 && bewaffnete == 0) {
/* abbruch, falls unbewaffnet oder unfaehig, katapulte zu benutzen */
cmistake(u, ord, 80, MSG_EVENT);
return 80;
}
if (!is_guard(u, GUARD_TRAVELTHRU)) {
/* abbruch, wenn die einheit nicht vorher die region bewacht - als
* warnung fuer alle anderen! */
cmistake(u, ord, 81, MSG_EVENT);
return 81;
}
/* einheit und burg markieren - spart zeit beim behandeln der einheiten
* in der burg, falls die burg auch markiert ist und nicht alle
* einheiten wieder abgesucht werden muessen! */
usetsiege(u, b);
b->besieged += _max(bewaffnete, katapultiere);
/* definitiver schaden eingeschraenkt */
d = _min(d, b->size - 1);
/* meldung, schaden anrichten */
if (d && !curse_active(get_curse(b->attribs, magicwalls_ct))) {
b->size -= d;
use_pooled(u, it_catapultammo->rtype,
GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, d);
/* send message to the entire region */
ADDMSG(&r->msgs, msg_message("siege_catapults",
"unit building destruction", u, b, d));
} else {
/* send message to the entire region */
ADDMSG(&r->msgs, msg_message("siege", "unit building", u, b));
}
return 0;
}
void do_siege(region * r)

View File

@ -1450,6 +1450,7 @@ static int buildingmaintenance(const building * b, const resource_type * rtype)
static int
report_template(const char *filename, report_context * ctx, const char *charset)
{
const resource_type *rsilver = get_resourcetype(R_SILVER);
faction *f = ctx->f;
region *r;
FILE *F = fopen(filename, "wt");
@ -1538,7 +1539,7 @@ report_template(const char *filename, report_context * ctx, const char *charset)
WARN_STATIC_BUFFER();
if (u->building && building_owner(u->building)==u) {
building *b = u->building;
int cost = buildingmaintenance(b, r_silver);
int cost = buildingmaintenance(b, rsilver);
if (cost > 0) {
bytes = (int)strlcpy(bufp, ",U", size);

View File

@ -4087,13 +4087,13 @@ static int sp_pump(castorder * co)
*/
static int sp_seduce(castorder * co)
{
item *items = NULL;
unit *target;
item **itmp;
unit *mage = co->magician.u;
spellparameter *pa = co->par;
int cast_level = co->level;
float force = co->force;
const resource_type *rsilver = get_resourcetype(R_SILVER);
unit *target;
item **itmp, *items = 0;;
unit *mage = co->magician.u;
spellparameter *pa = co->par;
int cast_level = co->level;
float force = co->force;
/* wenn kein Ziel gefunden, Zauber abbrechen */
if (pa->param[0]->flag == TARGET_NOTFOUND)
@ -4113,7 +4113,7 @@ static int sp_seduce(castorder * co)
while (*itmp) {
item *itm = *itmp;
int loot;
if (itm->type == i_silver) {
if (itm->type->rtype == rsilver) {
loot =
_min(cast_level * 1000, get_money(target) - (maintenance_cost(target)));
loot = _max(loot, 0);

View File

@ -314,7 +314,7 @@ summary *make_summary(void)
region *r;
unit *u;
summary *s = calloc(1, sizeof(summary));
const struct item_type *ihorse = it_find("horse");
const struct resource_type *rhorse = get_resourcetype(R_HORSE);
for (f = factions; f; f = f->next) {
const struct locale *lang = f->locale;
@ -384,7 +384,7 @@ summary *make_summary(void)
if (u->flags & UFL_HERO) {
s->heroes += u->number;
}
s->spielerpferde += i_get(u->items, ihorse);
s->spielerpferde += i_get(u->items, rhorse->itype);
s->playermoney += get_money(u);
s->armed_men += armedmen(u, true);
for (itm = u->items; itm; itm = itm->next) {
@ -396,7 +396,7 @@ summary *make_summary(void)
}
}
s->spielerpferde += i_get(u->items, ihorse);
s->spielerpferde += i_get(u->items, rhorse->itype);
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
skill_t sk = sv->id;