sanity-checks for potential divisions by zero (u->number)

This commit is contained in:
Enno Rehling 2006-10-15 14:09:59 +00:00
parent 6eaca764fe
commit 94966e8eda
15 changed files with 78 additions and 63 deletions

View File

@ -1624,6 +1624,8 @@ make_cmd(unit * u, struct order * ord)
const char *s; const char *s;
const struct locale * lang = u->faction->locale; const struct locale * lang = u->faction->locale;
if (u->number==NULL) return;
init_tokens(ord); init_tokens(ord);
skip_token(); skip_token();
s = getstrtoken(); s = getstrtoken();

View File

@ -338,7 +338,7 @@ age_unit(region * r, unit * u)
} }
} else { } else {
++u->age; ++u->age;
if (u->race->age) { if (u->number>0 && u->race->age) {
u->race->age(u); u->race->age(u);
} }
} }

View File

@ -309,6 +309,7 @@ static void
get_allies(region * r, unit * u) get_allies(region * r, unit * u)
{ {
unit *newunit = NULL; unit *newunit = NULL;
assert(u->number);
switch (rterrain(r)) { switch (rterrain(r)) {
@ -422,27 +423,24 @@ void
encounters(void) encounters(void)
{ {
region *r; region *r;
unit *u;
int n;
int c;
int i;
for (r = regions; r; r = r->next) { for (r = regions; r; r = r->next) {
if (!fval(r->terrain, SEA_REGION) && fval(r, RF_ENCOUNTER)) { if (!fval(r->terrain, SEA_REGION) && fval(r, RF_ENCOUNTER)) {
c = 0; int c = 0;
unit * u;
for (u = r->units; u; u = u->next) { for (u = r->units; u; u = u->next) {
c += u->number; c += u->number;
} }
if (c > 0) { if (c > 0) {
n = rng_int() % c; int i = 0;
u = r->units; int n = rng_int() % c;
for (i = u->number; i < n; i += u->number) { for (u = r->units; u; u = u->next) {
u = u->next; if (i+u->number>c) break;
} }
assert(u && u->number);
encounter(r, u); encounter(r, u);
} }
} }
} }
@ -609,12 +607,13 @@ damage_unit(unit *u, const char *dam, boolean physical, boolean magic)
int *hp = malloc(u->number * sizeof(int)); int *hp = malloc(u->number * sizeof(int));
int h; int h;
int i, dead = 0, hp_rem = 0, heiltrank; int i, dead = 0, hp_rem = 0, heiltrank;
double magres = magic_resistance(u);
assert(u->number);
if (fval(u->race, RCF_ILLUSIONARY) || u->race == new_race[RC_SPELL]) { if (fval(u->race, RCF_ILLUSIONARY) || u->race == new_race[RC_SPELL]) {
return 0; return 0;
} }
if (u->number==0) return 0;
h = u->hp/u->number; h = u->hp/u->number;
/* HP verteilen */ /* HP verteilen */
for (i=0; i<u->number; i++) hp[i] = h; for (i=0; i<u->number; i++) hp[i] = h;
@ -624,7 +623,7 @@ damage_unit(unit *u, const char *dam, boolean physical, boolean magic)
/* Schaden */ /* Schaden */
for (i=0; i<u->number; i++) { for (i=0; i<u->number; i++) {
int damage = dice_rand(dam); int damage = dice_rand(dam);
if (magic) damage = (int)(damage * (1.0 - magic_resistance(u))); if (magic) damage = (int)(damage * (1.0 - magres));
if (physical) damage -= nb_armor(u, i); if (physical) damage -= nb_armor(u, i);
hp[i] -= damage; hp[i] -= damage;
} }
@ -766,19 +765,21 @@ volcano_outbreak(region *r)
for (up=&r->units; *up;) { for (up=&r->units; *up;) {
unit * u = *up; unit * u = *up;
int dead = damage_unit(u, "4d10", true, false); if (u->number) {
if (dead) { int dead = damage_unit(u, "4d10", true, false);
ADDMSG(&u->faction->msgs, msg_message("volcano_dead", if (dead) {
"unit region dead", u, r, dead)); ADDMSG(&u->faction->msgs, msg_message("volcano_dead",
} "unit region dead", u, r, dead));
if (!fval(u->faction, FL_DH)) { }
fset(u->faction, FL_DH); if (!fval(u->faction, FL_DH)) {
if (rn) { fset(u->faction, FL_DH);
ADDMSG(&u->faction->msgs, msg_message("volcanooutbreak", if (rn) {
"regionv regionn", r, rn)); ADDMSG(&u->faction->msgs, msg_message("volcanooutbreak",
} else { "regionv regionn", r, rn));
ADDMSG(&u->faction->msgs, msg_message("volcanooutbreaknn", } else {
"region", r)); ADDMSG(&u->faction->msgs, msg_message("volcanooutbreaknn",
"region", r));
}
} }
} }
if (u==*up) up=&u->next; if (u==*up) up=&u->next;
@ -805,10 +806,12 @@ volcano_outbreak(region *r)
/* Personen bekommen 3W10 Punkte Schaden. */ /* Personen bekommen 3W10 Punkte Schaden. */
for (up=&rn->units; *up;) { for (up=&rn->units; *up;) {
unit * u = *up; unit * u = *up;
int dead = damage_unit(u, "3d10", true, false); if (u->number) {
if (dead) { int dead = damage_unit(u, "3d10", true, false);
ADDMSG(&u->faction->msgs, msg_message("volcano_dead", if (dead) {
"unit region dead", u, r, dead)); ADDMSG(&u->faction->msgs, msg_message("volcano_dead",
"unit region dead", u, r, dead));
}
} }
if (u==*up) up=&u->next; if (u==*up) up=&u->next;
} }

View File

@ -446,11 +446,7 @@ learn_cmd(unit * u, order * ord)
int p; int p;
magic_t mtyp; magic_t mtyp;
int l; int l;
int studycost; int studycost, days;
/* lernen nach lehren */
int days;
double multi = 1.0; double multi = 1.0;
attrib * a = NULL; attrib * a = NULL;
teaching_info * teach = NULL; teaching_info * teach = NULL;
@ -458,6 +454,7 @@ learn_cmd(unit * u, order * ord)
skill_t sk; skill_t sk;
int maxalchemy = 0; int maxalchemy = 0;
if (u->number==0) return;
if (fval(r->terrain, SEA_REGION)) { if (fval(r->terrain, SEA_REGION)) {
/* sonderbehandlung aller die auf Ozeanen lernen können */ /* sonderbehandlung aller die auf Ozeanen lernen können */
if (u->race!=new_race[RC_AQUARIAN] && !(u->race->flags & RCF_SWIM)) { if (u->race!=new_race[RC_AQUARIAN] && !(u->race->flags & RCF_SWIM)) {

View File

@ -911,6 +911,7 @@ terminate(troop dt, troop at, int type, const char *damage, boolean missile)
boolean magic = false; boolean magic = false;
int da = dice_rand(damage); int da = dice_rand(damage);
assert(du->number>0);
#ifdef SHOW_KILLS #ifdef SHOW_KILLS
++at.fighter->hits; ++at.fighter->hits;
#endif #endif
@ -2914,6 +2915,7 @@ make_fighter(battle * b, unit * u, side * s1, boolean attack)
static boolean init = false; static boolean init = false;
unsigned int flags = 0; unsigned int flags = 0;
assert(u->number);
if (fval(u, UFL_PARTEITARNUNG)!=0) flags |= SIDE_STEALTH; if (fval(u, UFL_PARTEITARNUNG)!=0) flags |= SIDE_STEALTH;
#ifdef SIMPLE_COMBAT #ifdef SIMPLE_COMBAT
if (attack) flags |= SIDE_ATTACKER; if (attack) flags |= SIDE_ATTACKER;

View File

@ -452,6 +452,7 @@ build_road(region * r, unit * u, int size, direction_t d)
int n, left; int n, left;
region * rn = rconnect(r,d); region * rn = rconnect(r,d);
assert(u->number);
if (!eff_skill(u, SK_ROAD_BUILDING, r)) { if (!eff_skill(u, SK_ROAD_BUILDING, r)) {
cmistake(u, u->thisorder, 103, MSG_PRODUCE); cmistake(u, u->thisorder, 103, MSG_PRODUCE);
return; return;
@ -611,6 +612,7 @@ build(unit * u, const construction * ctype, int completed, int want)
int made = 0; int made = 0;
int basesk, effsk; int basesk, effsk;
assert(u->number);
if (want<=0) return 0; if (want<=0) return 0;
if (type==NULL) return 0; if (type==NULL) return 0;
if (type->improvement==NULL && completed==type->maxsize) if (type->improvement==NULL && completed==type->maxsize)
@ -796,6 +798,7 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
order * new_order = NULL; order * new_order = NULL;
const struct locale * lang = u->faction->locale; const struct locale * lang = u->faction->locale;
assert(u->number);
if (eff_skill(u, SK_BUILDING, r) == 0) { if (eff_skill(u, SK_BUILDING, r) == 0) {
cmistake(u, ord, 101, MSG_PRODUCE); cmistake(u, ord, 101, MSG_PRODUCE);
return; return;

View File

@ -546,7 +546,7 @@ create_curse(unit *magician, attrib **ap, const curse_type *ct, double vigour,
/* hier müssen alle c-typen, die auf Einheiten gezaubert werden können, /* hier müssen alle c-typen, die auf Einheiten gezaubert werden können,
* berücksichtigt werden */ * berücksichtigt werden */
void static void
do_transfer_curse(curse *c, unit * u, unit * u2, int n) do_transfer_curse(curse *c, unit * u, unit * u2, int n)
{ {
int flag = c->flag; int flag = c->flag;

View File

@ -881,7 +881,7 @@ scale_number (unit * u, int n)
int remain; int remain;
if (n == u->number) return; if (n == u->number) return;
if (n && u->number) { if (n && u->number>0) {
int full; int full;
remain = ((u->hp%u->number) * (n % u->number)) % u->number; remain = ((u->hp%u->number) * (n % u->number)) % u->number;
@ -894,17 +894,19 @@ scale_number (unit * u, int n)
remain = 0; remain = 0;
u->hp = 0; u->hp = 0;
} }
for (a = a_find(u->attribs, &at_effect);a && a->type==&at_effect;a=a->next) { if (u->number>0) {
effect_data * data = (effect_data *)a->data.v; for (a = a_find(u->attribs, &at_effect);a && a->type==&at_effect;a=a->next) {
int snew = data->value / u->number * n; effect_data * data = (effect_data *)a->data.v;
if (n) { int snew = data->value / u->number * n;
remain = data->value - snew / n * u->number; if (n) {
snew += remain * n / u->number; remain = data->value - snew / n * u->number;
remain = (remain * n) % u->number; snew += remain * n / u->number;
if ((rng_int() % u->number) < remain) remain = (remain * n) % u->number;
++snew; /* Nachkommastellen */ if ((rng_int() % u->number) < remain)
++snew; /* Nachkommastellen */
}
data->value = snew;
} }
data->value = snew;
} }
if (u->number==0 || n==0) { if (u->number==0 || n==0) {
for (sk = 0; sk < MAXSKILLS; sk++) { for (sk = 0; sk < MAXSKILLS; sk++) {

View File

@ -1085,6 +1085,7 @@ magic_resistance(unit *target)
/* Bonus durch Rassenmagieresistenz */ /* Bonus durch Rassenmagieresistenz */
double probability = target->race->magres; double probability = target->race->magres;
assert(target->number>0);
/* Magier haben einen Resistenzbonus vom Magietalent * 5%*/ /* Magier haben einen Resistenzbonus vom Magietalent * 5%*/
probability += effskill(target, SK_MAGIC)*0.05; probability += effskill(target, SK_MAGIC)*0.05;

View File

@ -1249,6 +1249,7 @@ movement_speed(unit * u)
static boolean init = false; static boolean init = false;
double dk = u->race->speed; double dk = u->race->speed;
assert(u->number);
/* dragons have a fixed speed, and no other effects work on them: */ /* dragons have a fixed speed, and no other effects work on them: */
switch (old_race(u->race)) { switch (old_race(u->race)) {
case RC_DRAGON: case RC_DRAGON:
@ -2051,6 +2052,7 @@ move(unit * u, boolean move_on_land)
{ {
region_list * route = NULL; region_list * route = NULL;
assert(u->number);
if (u->ship && fval(u, UFL_OWNER)) { if (u->ship && fval(u, UFL_OWNER)) {
sail(u, u->thisorder, move_on_land, &route); sail(u, u->thisorder, move_on_land, &route);
} else { } else {

View File

@ -132,6 +132,7 @@ hp_status(const unit * u)
void void
report_item(const unit * owner, const item * i, const faction * viewer, const char ** name, const char ** basename, int * number, boolean singular) report_item(const unit * owner, const item * i, const faction * viewer, const char ** name, const char ** basename, int * number, boolean singular)
{ {
assert(owner->number);
if (owner->faction == viewer) { if (owner->faction == viewer) {
if (name) *name = locale_string(viewer->locale, resourcename(i->type->rtype, ((i->number!=1 && !singular)?GR_PLURAL:0))); if (name) *name = locale_string(viewer->locale, resourcename(i->type->rtype, ((i->number!=1 && !singular)?GR_PLURAL:0)));
if (basename) *basename = resourcename(i->type->rtype, 0); if (basename) *basename = resourcename(i->type->rtype, 0);

View File

@ -1077,16 +1077,18 @@ readunit(FILE * F)
assert(u->race); assert(u->race);
if (global.data_version<NEWSKILL_VERSION) { if (global.data_version<NEWSKILL_VERSION) {
/* convert old data */ /* convert old data */
while ((sk = (skill_t) ri(F)) != NOSKILL) { if (u->number) {
int days = ri(F) / u->number; while ((sk = (skill_t) ri(F)) != NOSKILL) {
int lvl = level(days); int days = ri(F) / u->number;
int weeks = lvl + 1 - (days - level_days(lvl))/30; int lvl = level(days);
assert(weeks>0 && weeks<=lvl+1); int weeks = lvl + 1 - (days - level_days(lvl))/30;
if (lvl) { assert(weeks>0 && weeks<=lvl+1);
skill * sv = add_skill(u, sk); if (lvl) {
sv->level = sv->old = (unsigned char)lvl; skill * sv = add_skill(u, sk);
sv->weeks = (unsigned char)weeks; sv->level = sv->old = (unsigned char)lvl;
} sv->weeks = (unsigned char)weeks;
}
}
} }
} else { } else {
while ((sk = (skill_t) ri(F)) != NOSKILL) { while ((sk = (skill_t) ri(F)) != NOSKILL) {

View File

@ -782,8 +782,8 @@ transfermen(unit * u, unit * u2, int n)
int hp = u->hp; int hp = u->hp;
region * r = u->region; region * r = u->region;
if (!n) return; if (n==0) return;
assert(n > 0);
/* "hat attackiert"-status wird übergeben */ /* "hat attackiert"-status wird übergeben */
if (u2) { if (u2) {

View File

@ -31,7 +31,7 @@
void void
age_firedragon(unit *u) age_firedragon(unit *u)
{ {
if (rng_int()%100 < age_chance(u->age, DRAGONAGE, 1)) { if (u->number>0 && rng_int()%100 < age_chance(u->age, DRAGONAGE, 1)) {
double q = (double) u->hp / (double) (unit_max_hp(u) * u->number); double q = (double) u->hp / (double) (unit_max_hp(u) * u->number);
u->race = new_race[RC_DRAGON]; u->race = new_race[RC_DRAGON];
u->irace = new_race[RC_DRAGON]; u->irace = new_race[RC_DRAGON];
@ -43,7 +43,7 @@ age_firedragon(unit *u)
void void
age_dragon(unit *u) age_dragon(unit *u)
{ {
if (rng_int()%100 < age_chance(u->age, WYRMAGE, 1)) { if (u->number>0 && rng_int()%100 < age_chance(u->age, WYRMAGE, 1)) {
double q = (double) u->hp / (double) (unit_max_hp(u) * u->number); double q = (double) u->hp / (double) (unit_max_hp(u) * u->number);
u->race = new_race[RC_WYRM]; u->race = new_race[RC_WYRM];
u->irace = new_race[RC_WYRM]; u->irace = new_race[RC_WYRM];

View File

@ -4708,7 +4708,7 @@ sp_headache(castorder *co)
countspells(mage, 1); countspells(mage, 1);
/* wenn kein Ziel gefunden, Zauber abbrechen */ /* wenn kein Ziel gefunden, Zauber abbrechen */
if(pa->param[0]->flag == TARGET_NOTFOUND) return 0; if (target->number==0 || pa->param[0]->flag == TARGET_NOTFOUND) return 0;
target = pa->param[0]->data.u; /* Zieleinheit */ target = pa->param[0]->data.u; /* Zieleinheit */