Merge pull request #835 from ennorehling/develop

ongoing changes
This commit is contained in:
Enno Rehling 2019-02-03 04:23:31 +01:00 committed by GitHub
commit 1ea064d1f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 169 additions and 132 deletions

View file

@ -1182,3 +1182,21 @@ function test_cartmaking()
assert_equal(1, u:get_item('cart')) assert_equal(1, u:get_item('cart'))
assert_equal(5, u:get_item('log')) assert_equal(5, u:get_item('log'))
end end
function test_promote_after_recruit()
local f = faction.create('human')
local r1 = region.create(0, 0, 'plain')
local r2 = region.create(1, 0, 'plain')
local u1 = unit.create(f, r1, 1)
u1.name = 'Xolgrim'
local u2 = unit.create(f, r2, 55)
u2:add_order('REKRUTIERE 1')
u1:add_order('BEFOERDERE')
u1:add_item('money', 57)
u2:add_item('money', 150)
local fl = u1.flags
process_orders()
assert_equal(56, u2.number)
assert_equal(fl + 128, u1.flags) -- UFL_HERO
assert_equal(0, u1:get_item('money'))
end

View file

@ -27,7 +27,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "study.h" #include "study.h"
void academy_teaching_bonus(struct unit *u, skill_t sk, int students) { void academy_teaching_bonus(struct unit *u, skill_t sk, int students) {
if (students && sk != NOSKILL) { if (students > 0 && sk != NOSKILL) {
/* actually students * EXPERIENCEDAYS / MAX_STUDENTS */ /* actually students * EXPERIENCEDAYS / MAX_STUDENTS */
learn_skill(u, sk, students); learn_skill(u, sk, students);
} }

View file

@ -16,7 +16,10 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/ **/
#ifdef _MSC_VER
#include <platform.h> #include <platform.h>
#endif
#include <kernel/config.h> #include <kernel/config.h>
#include "battle.h" #include "battle.h"
#include "alchemy.h" #include "alchemy.h"
@ -436,7 +439,8 @@ static int get_row(const side * s, int row, const side * vs)
/* every entry in the size[] array means someone trying to defend us. /* every entry in the size[] array means someone trying to defend us.
* 'retreat' is the number of rows falling. * 'retreat' is the number of rows falling.
*/ */
result = MAX(FIRST_ROW, row - retreat); result = row - retreat;
if (result < FIRST_ROW) result = FIRST_ROW;
return result; return result;
} }
@ -587,50 +591,27 @@ weapon_skill(const weapon_type * wtype, const unit * u, bool attacking)
* are taken into account, e.g. no horses, magic, etc. */ * are taken into account, e.g. no horses, magic, etc. */
{ {
int skill; int skill;
const race * rc = u_race(u);
if (wtype == NULL) { if (wtype == NULL) {
skill = effskill(u, SK_WEAPONLESS, NULL); skill = effskill(u, SK_WEAPONLESS, NULL);
int def = attacking ? rc->at_default : rc->df_default;
if (skill <= 0) { if (skill <= 0) {
/* wenn kein waffenloser kampf, dann den rassen-defaultwert */ /* wenn kein waffenloser kampf, dann den rassen-defaultwert */
if (u_race(u) == get_race(RC_ORC)) { if (rc == get_race(RC_ORC)) {
int sword = effskill(u, SK_MELEE, NULL); int sword = effskill(u, SK_MELEE, NULL);
int spear = effskill(u, SK_SPEAR, NULL); int spear = effskill(u, SK_SPEAR, NULL);
skill = MAX(sword, spear) - 3; skill = ((sword > spear) ? sword : spear) - 3;
if (attacking) {
skill = MAX(skill, u_race(u)->at_default);
}
else {
skill = MAX(skill, u_race(u)->df_default);
}
}
else {
if (attacking) {
skill = u_race(u)->at_default;
}
else {
skill = u_race(u)->df_default;
}
}
}
else {
/* der rassen-defaultwert kann h<>her sein als der Talentwert von
* waffenloser kampf */
if (attacking) {
if (skill < u_race(u)->at_default)
skill = u_race(u)->at_default;
}
else {
if (skill < u_race(u)->df_default)
skill = u_race(u)->df_default;
} }
} }
if (def > skill) skill = def;
if (attacking) { if (attacking) {
skill += u_race(u)->at_bonus; skill += rc->at_bonus;
if (fval(u->region->terrain, SEA_REGION) && u->ship) if (fval(u->region->terrain, SEA_REGION) && u->ship)
skill += u->ship->type->at_bonus; skill += u->ship->type->at_bonus;
} }
else { else {
skill += u_race(u)->df_bonus; skill += rc->df_bonus;
if (fval(u->region->terrain, SEA_REGION) && u->ship) if (fval(u->region->terrain, SEA_REGION) && u->ship)
skill += u->ship->type->df_bonus; skill += u->ship->type->df_bonus;
} }
@ -642,10 +623,10 @@ weapon_skill(const weapon_type * wtype, const unit * u, bool attacking)
skill = effskill(u, wtype->skill, NULL); skill = effskill(u, wtype->skill, NULL);
if (skill > 0) { if (skill > 0) {
if (attacking) { if (attacking) {
skill += u_race(u)->at_bonus; skill += rc->at_bonus;
} }
else { else {
skill += u_race(u)->df_bonus; skill += rc->df_bonus;
} }
} }
if (attacking) { if (attacking) {
@ -1261,32 +1242,33 @@ static int apply_race_resistance(int reduced_damage, fighter *df,
static int apply_magicshield(int reduced_damage, fighter *df, static int apply_magicshield(int reduced_damage, fighter *df,
const weapon_type *awtype, battle *b, bool magic) { const weapon_type *awtype, battle *b, bool magic) {
side *ds = df->side; side *ds = df->side;
selist *ql; selist *ql;
int qi; int qi;
if (reduced_damage <= 0) if (reduced_damage <= 0)
return 0; return 0;
/* Schilde */ /* Schilde */
for (qi = 0, ql = b->meffects; ql; selist_advance(&ql, &qi, 1)) { for (qi = 0, ql = b->meffects; ql; selist_advance(&ql, &qi, 1)) {
meffect *me = (meffect *) selist_get(ql, qi); meffect *me = (meffect *)selist_get(ql, qi);
if (meffect_protection(b, me, ds) != 0) { if (meffect_protection(b, me, ds) != 0) {
assert(0 <= reduced_damage); /* rda sollte hier immer mindestens 0 sein */ assert(0 <= reduced_damage); /* rda sollte hier immer mindestens 0 sein */
/* jeder Schaden wird um effect% reduziert bis der Schild duration /* jeder Schaden wird um effect% reduziert bis der Schild duration
* Trefferpunkte aufgefangen hat */ * Trefferpunkte aufgefangen hat */
if (me->typ == SHIELD_REDUCE) { if (me->typ == SHIELD_REDUCE) {
int hp = reduced_damage * (me->effect / 100); int hp = reduced_damage * (me->effect / 100);
reduced_damage -= hp; reduced_damage -= hp;
me->duration -= hp; me->duration -= hp;
} }
/* gibt R<>stung +effect f<>r duration Treffer */ /* gibt R<>stung +effect f<>r duration Treffer */
if (me->typ == SHIELD_ARMOR) { if (me->typ == SHIELD_ARMOR) {
reduced_damage = MAX(reduced_damage - me->effect, 0); reduced_damage -= me->effect;
me->duration--; if (reduced_damage < 0) reduced_damage = 0;
} me->duration--;
}
}
} }
}
return reduced_damage; return reduced_damage;
} }
@ -1347,11 +1329,13 @@ terminate(troop dt, troop at, int type, const char *damage_formula, bool missile
/* Skilldifferenzbonus */ /* Skilldifferenzbonus */
if (rule_damage & DAMAGE_SKILL_BONUS) { if (rule_damage & DAMAGE_SKILL_BONUS) {
damage += MAX(0, (attskill - defskill) / DAMAGE_QUOTIENT); int b = (attskill - defskill) / DAMAGE_QUOTIENT;
if (b > 0) damage += b;
} }
} }
reduced_damage = MAX(damage - armor_value, 0); reduced_damage = damage - armor_value;
if (reduced_damage < 0) reduced_damage = 0;
reduced_damage = apply_race_resistance(reduced_damage, df, awtype, magic); reduced_damage = apply_race_resistance(reduced_damage, df, awtype, magic);
reduced_damage = apply_magicshield(reduced_damage, df, awtype, b, magic); reduced_damage = apply_magicshield(reduced_damage, df, awtype, b, magic);
@ -1500,7 +1484,8 @@ troop select_enemy(fighter * af, int minrow, int maxrow, int select)
minrow = FIGHT_ROW; minrow = FIGHT_ROW;
maxrow = BEHIND_ROW; maxrow = BEHIND_ROW;
} }
minrow = MAX(minrow, FIGHT_ROW);
if (minrow < FIGHT_ROW) minrow = FIGHT_ROW;
enemies = count_enemies(b, af, minrow, maxrow, select); enemies = count_enemies(b, af, minrow, maxrow, select);
@ -1611,7 +1596,7 @@ static troop select_opponent(battle * b, troop at, int mindist, int maxdist)
dt = select_enemy(at.fighter, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE); dt = select_enemy(at.fighter, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
} }
else { else {
mindist = MAX(mindist, FIGHT_ROW); if (mindist < FIGHT_ROW) mindist = FIGHT_ROW;
dt = select_enemy(at.fighter, mindist, maxdist, SELECT_ADVANCE); dt = select_enemy(at.fighter, mindist, maxdist, SELECT_ADVANCE);
} }
@ -2078,7 +2063,8 @@ void dazzle(battle * b, troop * td)
void damage_building(battle * b, building * bldg, int damage_abs) void damage_building(battle * b, building * bldg, int damage_abs)
{ {
assert(bldg); assert(bldg);
bldg->size = MAX(1, bldg->size - damage_abs); bldg->size -= damage_abs;
if (bldg->size < 1) bldg->size = 1;
/* Wenn Burg, dann gucken, ob die Leute alle noch in das Geb<65>ude passen. */ /* Wenn Burg, dann gucken, ob die Leute alle noch in das Geb<65>ude passen. */
@ -3020,7 +3006,9 @@ static void print_stats(battle * b)
for (s = b->sides; s != b->sides + b->nsides; ++s) { for (s = b->sides; s != b->sides + b->nsides; ++s) {
if (!selist_empty(s->leader.fighters)) { if (!selist_empty(s->leader.fighters)) {
b->max_tactics = MAX(b->max_tactics, s->leader.value); if (s->leader.value > b->max_tactics) {
b->max_tactics = s->leader.value;
}
} }
} }
@ -3371,7 +3359,7 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack)
else else
p_bonus += 3; p_bonus += 3;
} while (rnd >= 97); } while (rnd >= 97);
bonus = MAX(p_bonus, bonus); if (p_bonus > bonus) p_bonus = bonus;
} }
tactics += bonus; tactics += bonus;
} }

View file

@ -16,7 +16,10 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/ **/
#include <platform.h> #ifdef _MSC_VER
# include <platform.h>
#endif
#include "weapons.h" #include "weapons.h"
#include "battle.h" #include "battle.h"
@ -106,7 +109,7 @@ int *casualties)
} }
enemies = count_enemies(b, af, FIGHT_ROW, FIGHT_ROW, SELECT_ADVANCE); enemies = count_enemies(b, af, FIGHT_ROW, FIGHT_ROW, SELECT_ADVANCE);
enemies = MIN(enemies, CATAPULT_ATTACKS); if (enemies > CATAPULT_ATTACKS) enemies = CATAPULT_ATTACKS;
if (enemies == 0) { if (enemies == 0) {
return true; /* allow further attacks */ return true; /* allow further attacks */
} }

View file

@ -75,8 +75,9 @@ use_manacrystal(struct unit *u, const struct item_type *itype, int amount,
} }
msp = max_spellpoints_depr(u->region, u) / 2; msp = max_spellpoints_depr(u->region, u) / 2;
if (msp < 25) msp = 25;
for (i = 0; i != amount; ++i) { for (i = 0; i != amount; ++i) {
sp += MAX(25, msp); sp += msp;
change_spellpoints(u, sp); change_spellpoints(u, sp);
} }

View file

@ -60,7 +60,7 @@ group *new_group(faction * f, const char *name, int gid)
gp = &(*gp)->next; gp = &(*gp)->next;
*gp = g; *gp = g;
maxgid = MAX(gid, maxgid); if (gid > maxgid) maxgid = gid;
g->name = str_strdup(name); g->name = str_strdup(name);
g->gid = gid; g->gid = gid;

View file

@ -10,7 +10,10 @@
without prior permission by the authors of Eressea. without prior permission by the authors of Eressea.
*/ */
#ifdef _MSC_VER
#include <platform.h> #include <platform.h>
#endif
#include <kernel/config.h> #include <kernel/config.h>
#include "order.h" #include "order.h"
@ -398,6 +401,7 @@ order *parse_order(const char *s, const struct locale * lang)
} }
if (kwd != NOKEYWORD) { if (kwd != NOKEYWORD) {
order *ord = (order *)malloc(sizeof(order)); order *ord = (order *)malloc(sizeof(order));
if (ord == NULL) abort();
create_order_i(ord, kwd, sptr, persistent, noerror, lang); create_order_i(ord, kwd, sptr, persistent, noerror, lang);
return ord; return ord;
} }

View file

@ -156,7 +156,7 @@ int set_resvalue(unit * u, const item_type * itype, int value)
} }
int int
get_pooled(const unit * u, const resource_type * rtype, unsigned int mode, get_pooled(const unit * u, const resource_type * rtype, int mode,
int count) int count)
{ {
const faction *f = u->faction; const faction *f = u->faction;
@ -199,7 +199,7 @@ int count)
} }
int int
use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count) use_pooled(unit * u, const resource_type * rtype, int mode, int count)
{ {
const faction *f = u->faction; const faction *f = u->faction;
unit *v; unit *v;

View file

@ -42,9 +42,9 @@ extern "C" {
#define GET_ALL (GET_SLACK|GET_RESERVE|GET_POOLED_SLACK|GET_POOLED_RESERVE|GET_POOLED_FORCE) #define GET_ALL (GET_SLACK|GET_RESERVE|GET_POOLED_SLACK|GET_POOLED_RESERVE|GET_POOLED_FORCE)
int get_pooled(const struct unit *u, const struct resource_type *res, int get_pooled(const struct unit *u, const struct resource_type *res,
unsigned int mode, int count); int mode, int count);
int use_pooled(struct unit *u, const struct resource_type *res, int use_pooled(struct unit *u, const struct resource_type *res,
unsigned int mode, int count); int mode, int count);
/** use_pooled /** use_pooled
* verbraucht 'count' Objekte der resource 'itm' * verbraucht 'count' Objekte der resource 'itm'
* unter zuhilfenahme des Pools der struct region und Aufbrauch des * unter zuhilfenahme des Pools der struct region und Aufbrauch des

View file

@ -16,7 +16,10 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/ **/
#include <platform.h> #ifdef _MSC_VER
# include <platform.h>
#endif
#include "region.h" #include "region.h"
/* kernel includes */ /* kernel includes */
@ -141,8 +144,11 @@ const char *regionname(const region * r, const faction * f)
int region_maxworkers(const region *r) int region_maxworkers(const region *r)
{ {
int size = max_production(r); int size = max_production(r);
int treespace = (rtrees(r, 2) + rtrees(r, 1) / 2) * TREESIZE; int treespace = size - (rtrees(r, 2) + rtrees(r, 1) / 2) * TREESIZE;
return MAX(size - treespace, MIN(size / 10, 200)); size /=10;
if (size > 200) size = 200;
if (treespace < size) treespace = size;
return treespace;
} }
int deathcount(const region * r) int deathcount(const region * r)
@ -400,7 +406,7 @@ koor_distance_wrap_xy(int x1, int y1, int x2, int y2, int width, int height)
int dx = x1 - x2; int dx = x1 - x2;
int dy = y1 - y2; int dy = y1 - y2;
int result, dist; int result, dist;
int mindist = MIN(width, height) >> 1; int mindist = ((width > height) ? height : width) / 2;
/* Bei negativem dy am Ursprung spiegeln, das veraendert /* Bei negativem dy am Ursprung spiegeln, das veraendert
* den Abstand nicht * den Abstand nicht
@ -423,13 +429,15 @@ koor_distance_wrap_xy(int x1, int y1, int x2, int y2, int width, int height)
if (result <= mindist) if (result <= mindist)
return result; return result;
} }
dist = MAX(dx, height - dy); dist = height - dy;
if (dist < dx) dist = dx;
if (dist >= 0 && dist < result) { if (dist >= 0 && dist < result) {
result = dist; result = dist;
if (result <= mindist) if (result <= mindist)
return result; return result;
} }
dist = MAX(width - dx, dy); dist = width - dx;
if (dist < dy) dist = dy;
if (dist >= 0 && dist < result) if (dist >= 0 && dist < result)
result = dist; result = dist;
return result; return result;
@ -1097,7 +1105,8 @@ void init_region(region *r)
if (!fval(r, RF_CHAOTIC)) { if (!fval(r, RF_CHAOTIC)) {
int peasants; int peasants;
peasants = (region_maxworkers(r) * (20 + dice(6, 10))) / 100; peasants = (region_maxworkers(r) * (20 + dice(6, 10))) / 100;
rsetpeasants(r, MAX(100, peasants)); if (peasants < 100) peasants = 100;
rsetpeasants(r, peasants);
rsetmoney(r, rpeasants(r) * ((wage(r, NULL, NULL, rsetmoney(r, rpeasants(r) * ((wage(r, NULL, NULL,
INT_MAX) + 1) + rng_int() % 5)); INT_MAX) + 1) + rng_int() % 5));
} }
@ -1419,7 +1428,8 @@ faction *update_owners(region * r)
else if (f || new_owner->faction != region_get_last_owner(r)) { else if (f || new_owner->faction != region_get_last_owner(r)) {
alliance *al = region_get_alliance(r); alliance *al = region_get_alliance(r);
if (al && new_owner->faction->alliance == al) { if (al && new_owner->faction->alliance == al) {
int morale = MAX(0, region_get_morale(r) - MORALE_TRANSFER); int morale = region_get_morale(r) - MORALE_TRANSFER;
if (morale < 0) morale = 0;
region_set_morale(r, morale, turn); region_set_morale(r, morale, turn);
} }
else { else {

View file

@ -448,7 +448,7 @@ unit *read_unit(gamedata *data)
set_number(u, number); set_number(u, number);
READ_INT(data->store, &n); READ_INT(data->store, &n);
u->age = (short)n; u->age = n;
READ_TOK(data->store, rname, sizeof(rname)); READ_TOK(data->store, rname, sizeof(rname));
rc = rc_find(rname); rc = rc_find(rname);
@ -775,7 +775,8 @@ static region *readregion(gamedata *data, int x, int y)
} }
if (data->version >= REGIONOWNER_VERSION) { if (data->version >= REGIONOWNER_VERSION) {
READ_INT(data->store, &n); READ_INT(data->store, &n);
region_set_morale(r, MAX(0, (short)n), -1); if (n < 0) n = 0;
region_set_morale(r, n, -1);
read_owner(data, &r->land->ownership); read_owner(data, &r->land->ownership);
} }
} }

View file

@ -278,13 +278,11 @@ static void test_readwrite_dead_faction_group(CuTest *tc) {
CuAssertPtrEquals(tc, f2, factions); CuAssertPtrEquals(tc, f2, factions);
write_game(&data); write_game(&data);
free_gamedata(); free_gamedata();
f = f2 = NULL;
data.strm.api->rewind(data.strm.handle); data.strm.api->rewind(data.strm.handle);
read_game(&data); read_game(&data);
CuAssertPtrEquals(tc, NULL, findfaction(fno)); CuAssertPtrEquals(tc, NULL, findfaction(fno));
f2 = factions; CuAssertPtrNotNull(tc, factions);
CuAssertPtrNotNull(tc, f2); u = factions->units;
u = f2->units;
CuAssertPtrNotNull(tc, u); CuAssertPtrNotNull(tc, u);
g = get_group(u); g = get_group(u);
CuAssertPtrNotNull(tc, g); CuAssertPtrNotNull(tc, g);
@ -313,13 +311,11 @@ static void test_readwrite_dead_faction_regionowner(CuTest *tc) {
remove_empty_units(); remove_empty_units();
write_game(&data); write_game(&data);
free_gamedata(); free_gamedata();
f = NULL;
data.strm.api->rewind(data.strm.handle); data.strm.api->rewind(data.strm.handle);
read_game(&data); read_game(&data);
mstream_done(&data.strm); mstream_done(&data.strm);
gamedata_done(&data); gamedata_done(&data);
f = factions; CuAssertPtrEquals(tc, NULL, factions);
CuAssertPtrEquals(tc, NULL, f);
r = regions; r = regions;
CuAssertPtrNotNull(tc, r); CuAssertPtrNotNull(tc, r);
CuAssertPtrEquals(tc, NULL, region_get_owner(r)); CuAssertPtrEquals(tc, NULL, region_get_owner(r));

View file

@ -16,7 +16,9 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/ **/
#include <platform.h> #ifdef _MSC_VER
# include <platform.h>
#endif
#include <kernel/config.h> #include <kernel/config.h>
#include "ship.h" #include "ship.h"
@ -359,8 +361,9 @@ int shipspeed(const ship * sh, const unit * u)
int crew = crew_skill(sh); int crew = crew_skill(sh);
int crew_bonus = (crew / sh->type->sumskill / 2) - 1; int crew_bonus = (crew / sh->type->sumskill / 2) - 1;
if (crew_bonus > 0) { if (crew_bonus > 0) {
bonus = MIN(bonus, crew_bonus); int sbonus = sh->type->range_max - sh->type->range;
bonus = MIN(bonus, sh->type->range_max - sh->type->range); if (bonus > sbonus) bonus = sbonus;
if (bonus > crew_bonus) bonus = crew_bonus;
} }
else { else {
bonus = 0; bonus = 0;

View file

@ -16,7 +16,9 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/ **/
#include <platform.h> #ifdef _MSC_VER
# include <platform.h>
#endif
#include <kernel/config.h> #include <kernel/config.h>
#include "unit.h" #include "unit.h"
@ -1229,7 +1231,7 @@ int invisible(const unit * target, const unit * viewer)
else { else {
int hidden = item_invis(target); int hidden = item_invis(target);
if (hidden) { if (hidden) {
hidden = MIN(hidden, target->number); if (hidden > target->number) hidden = target->number;
if (viewer) { if (viewer) {
const resource_type *rtype = get_resourcetype(R_AMULET_OF_TRUE_SEEING); const resource_type *rtype = get_resourcetype(R_AMULET_OF_TRUE_SEEING);
hidden -= i_get(viewer->items, rtype->itype); hidden -= i_get(viewer->items, rtype->itype);

View file

@ -3840,6 +3840,10 @@ void init_processor(void)
add_proc_region(p, do_force_leave, "kick non-allies out of buildings/ships"); add_proc_region(p, do_force_leave, "kick non-allies out of buildings/ships");
} }
add_proc_region(p, economics, "Zerstoeren, Geben, Rekrutieren, Vergessen"); add_proc_region(p, economics, "Zerstoeren, Geben, Rekrutieren, Vergessen");
/* all recruitment must be finished before we can calculate
* promotion cost of ability */
p += 10;
add_proc_order(p, K_PROMOTION, promotion_cmd, 0, "Heldenbefoerderung"); add_proc_order(p, K_PROMOTION, promotion_cmd, 0, "Heldenbefoerderung");
p += 10; p += 10;

View file

@ -268,10 +268,10 @@ static int parse_args(int argc, char **argv)
#ifdef HAVE_BACKTRACE #ifdef HAVE_BACKTRACE
#include <execinfo.h> #include <execinfo.h>
#include <signal.h> #include <signal.h>
static void *btrace[50];
static void report_segfault(int signo, siginfo_t * sinf, void *arg) static void report_segfault(int signo, siginfo_t * sinf, void *arg)
{ {
void *btrace[50];
size_t size; size_t size;
int fd = fileno(stderr); int fd = fileno(stderr);

View file

@ -76,7 +76,8 @@ void morale_update(region *r) {
void morale_change(region *r, int value) { void morale_change(region *r, int value) {
int morale = region_get_morale(r); int morale = region_get_morale(r);
if (morale > 0) { if (morale > 0) {
morale = MAX(0, morale - value); morale = morale - value;
if (morale < 0) morale = 0;
region_set_morale(r, morale, turn); region_set_morale(r, morale, turn);
} }
} }

View file

@ -14,6 +14,3 @@
#pragma warning(disable: 4224) // formal parameter was previously defined as a type #pragma warning(disable: 4224) // formal parameter was previously defined as a type
#pragma warning(disable: 4214) // bit field types other than int #pragma warning(disable: 4214) // bit field types other than int
#endif #endif
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))

View file

@ -22,7 +22,10 @@
/* util includes */ /* util includes */
#include <util/rng.h> #include <util/rng.h>
#define age_chance(a,b,p) (MAX(0,a-b)*p) static int age_chance(int a, int b, int p) {
int r = (a - b) * p;
return (r < 0) ? 0 : r;
}
#define DRAGONAGE 27 #define DRAGONAGE 27
#define WYRMAGE 68 #define WYRMAGE 68

View file

@ -31,7 +31,10 @@
#define UNDEAD_BREAKUP 25 /* chance dafuer */ #define UNDEAD_BREAKUP 25 /* chance dafuer */
#define UNDEAD_BREAKUP_FRACTION (25+rng_int()%70) /* anteil der weg geht */ #define UNDEAD_BREAKUP_FRACTION (25+rng_int()%70) /* anteil der weg geht */
#define age_chance(a,b,p) (MAX(0,a-b)*p) static int age_chance(int a, int b, int p) {
int r = (a - b) * p;
return (r < 0) ? 0 : r;
}
void make_undead_unit(unit * u) void make_undead_unit(unit * u)
{ {
@ -43,8 +46,9 @@ void make_undead_unit(unit * u)
void age_skeleton(unit * u) void age_skeleton(unit * u)
{ {
if (is_monsters(u->faction) && rng_int() % 100 < age_chance(u->age, 27, 1)) { if (is_monsters(u->faction) && rng_int() % 100 < age_chance(u->age, 27, 1)) {
int n = MAX(1, u->number / 2); int n = u->number / 2;
double q = (double)u->hp / (double)(unit_max_hp(u) * u->number); double q = (double)u->hp / (double)(unit_max_hp(u) * u->number);
if (n < 1) n = 1;
u_setrace(u, get_race(RC_SKELETON_LORD)); u_setrace(u, get_race(RC_SKELETON_LORD));
u->irace = NULL; u->irace = NULL;
scale_number(u, n); scale_number(u, n);
@ -55,8 +59,9 @@ void age_skeleton(unit * u)
void age_zombie(unit * u) void age_zombie(unit * u)
{ {
if (is_monsters(u->faction) && rng_int() % 100 < age_chance(u->age, 27, 1)) { if (is_monsters(u->faction) && rng_int() % 100 < age_chance(u->age, 27, 1)) {
int n = MAX(1, u->number / 2); int n = u->number / 2;
double q = (double)u->hp / (double)(unit_max_hp(u) * u->number); double q = (double)u->hp / (double)(unit_max_hp(u) * u->number);
if (n < 1) n = 1;
u_setrace(u, get_race(RC_ZOMBIE_LORD)); u_setrace(u, get_race(RC_ZOMBIE_LORD));
u->irace = NULL; u->irace = NULL;
scale_number(u, n); scale_number(u, n);
@ -67,11 +72,11 @@ void age_zombie(unit * u)
void age_ghoul(unit * u) void age_ghoul(unit * u)
{ {
if (is_monsters(u->faction) && rng_int() % 100 < age_chance(u->age, 27, 1)) { if (is_monsters(u->faction) && rng_int() % 100 < age_chance(u->age, 27, 1)) {
int n = MAX(1, u->number / 2); int n = u->number / 2;
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_setrace(u, get_race(RC_GHOUL_LORD)); u_setrace(u, get_race(RC_GHOUL_LORD));
u->irace = NULL; u->irace = NULL;
scale_number(u, n); scale_number(u, (n > 0) ? n : 1);
u->hp = (int)(unit_max_hp(u) * u->number * q); u->hp = (int)(unit_max_hp(u) * u->number * q);
} }
} }

View file

@ -4089,7 +4089,7 @@ static int sp_pump(castorder * co)
* Betoert eine Einheit, so das sie ihm den groe<EFBFBD>ten Teil ihres Bargelds * Betoert eine Einheit, so das sie ihm den groe<EFBFBD>ten Teil ihres Bargelds
* und 50% ihres Besitzes schenkt. Sie behaelt jedoch immer soviel, wie * und 50% ihres Besitzes schenkt. Sie behaelt jedoch immer soviel, wie
* sie zum ueberleben braucht. Wirkt gegen Magieresistenz. * sie zum ueberleben braucht. Wirkt gegen Magieresistenz.
* MIN(Stufe*1000$, u->money - maintenance) * min(Stufe*1000$, u->money - maintenance)
* Von jedem Item wird 50% abgerundet ermittelt und uebergeben. Dazu * Von jedem Item wird 50% abgerundet ermittelt und uebergeben. Dazu
* kommt Itemzahl%2 mit 50% chance * kommt Itemzahl%2 mit 50% chance
* *

View file

@ -16,7 +16,10 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/ **/
#include <platform.h> #ifdef _MSC_VER
# include <platform.h>
#endif
#include "shock.h" #include "shock.h"
#include <magic.h> #include <magic.h>
@ -61,8 +64,8 @@ static void do_shock(unit * u, const char *reason)
if (u->number > 0) { if (u->number > 0) {
/* HP - Verlust */ /* HP - Verlust */
int hp = (unit_max_hp(u) * u->number) / 10; int hp = (unit_max_hp(u) * u->number) / 10;
hp = MIN(u->hp, hp); if (hp > u->hp) hp = u->hp;
u->hp = MAX(1, hp); u->hp = (hp > 1) ? hp : 1;
} }
/* Aura - Verlust */ /* Aura - Verlust */

View file

@ -306,8 +306,8 @@ char *str_unescape(char *str) {
char *read = str, *write = str; char *read = str, *write = str;
while (*read) { while (*read) {
char * pos = strchr(read, '\\'); char * pos = strchr(read, '\\');
if (pos) { if (pos >= read) {
size_t len = pos - read; size_t len = (size_t)(pos - read);
memmove(write, read, len); memmove(write, read, len);
write += len; write += len;
read += (len + 1); read += (len + 1);
@ -341,14 +341,14 @@ const char *str_escape_ex(const char *str, char *buffer, size_t size, const char
{ {
size_t slen = strlen(str); size_t slen = strlen(str);
const char *read = str; const char *read = str;
char *write = buffer; unsigned char *write = (unsigned char *)buffer;
if (size < 1) { if (size < 1) {
return NULL; return NULL;
} }
while (slen > 0 && size > 1 && *read) { while (slen > 0 && size > 1 && *read) {
const char *pos = strpbrk(read, chars); const char *pos = strpbrk(read, chars);
size_t len = size; size_t len = size;
if (pos) { if (pos >= read) {
len = pos - read; len = pos - read;
} }
if (len < size) { if (len < size) {
@ -399,7 +399,7 @@ const char *str_escape_ex(const char *str, char *buffer, size_t size, const char
break; break;
default: default:
if (size > 5) { if (size > 5) {
int n = sprintf(write, "\\%03o", ch); int n = snprintf((char *)write, size, "\\%03o", ch);
if (n > 0) { if (n > 0) {
assert(n == 5); assert(n == 5);
write += n; write += n;

View file

@ -164,10 +164,10 @@ static void free_functions(void)
void add_function(const char *symbol, evalfun parse) void add_function(const char *symbol, evalfun parse)
{ {
char token[64]; char token[64]; /* Flawfinder: ignore */
size_t len = strlen(symbol); size_t len = strlen(symbol);
assert(len + 1 + sizeof(parse) <= sizeof(token)); assert(len + sizeof(parse) < sizeof(token));
len = cb_new_kv(symbol, len, &parse, sizeof(parse), token); len = cb_new_kv(symbol, len, &parse, sizeof(parse), token);
cb_insert(&functions, token, len); cb_insert(&functions, token, len);
} }
@ -193,15 +193,17 @@ static const char *parse_symbol(opstack ** stack, const char *in,
*/ */
{ {
bool braces = false; bool braces = false;
char symbol[32]; char symbol[32]; /* Flawfinder: ignore */
char *cp = symbol; /* current position */ char *cp = symbol; /* current position */
if (*in == '{') { if (*in == '{') {
braces = true; braces = true;
++in; ++in;
} }
while (isalnum(*in) || *in == '.') while (isalnum(*in) || *in == '.') {
*cp++ = *in++; *cp++ = *in++;
assert(cp < symbol + sizeof(symbol));
}
*cp = '\0'; *cp = '\0';
/* symbol will now contain the symbol name */ /* symbol will now contain the symbol name */
if (*in == '(') { if (*in == '(') {
@ -371,7 +373,7 @@ const char *translate(const char *format, const void *userdata,
{ {
unsigned int i = 0; unsigned int i = 0;
const char *ic = vars; const char *ic = vars;
char symbol[32]; char symbol[32]; /* Flawfinder: ignore */
char *oc = symbol; char *oc = symbol;
opstack *stack = NULL; opstack *stack = NULL;
const char *rv; const char *rv;
@ -383,11 +385,15 @@ const char *translate(const char *format, const void *userdata,
assert(*ic == 0 || isalnum(*ic)); assert(*ic == 0 || isalnum(*ic));
while (*ic) { while (*ic) {
*oc++ = *ic++; *oc++ = *ic++;
assert(oc < symbol + sizeof(symbol));
if (!isalnum(*ic)) { if (!isalnum(*ic)) {
size_t len;
variant x = args[i++]; variant x = args[i++];
*oc = '\0'; *oc = '\0';
len = oc - symbol + 1;
str_strlcpy(oc = balloc(len), symbol, len);
add_variable(oc, x);
oc = symbol; oc = symbol;
add_variable(strcpy(balloc(strlen(symbol) + 1), symbol), x);
while (*ic && !isalnum(*ic)) while (*ic && !isalnum(*ic))
++ic; ++ic;
} }
@ -452,22 +458,15 @@ static void eval_if(opstack ** stack, const void *userdata)
UNUSED_ARG(userdata); UNUSED_ARG(userdata);
} }
static void eval_strlen(opstack ** stack, const void *userdata)
{ /* string -> int */
const char *c = (const char *)opop_v(stack);
opush_i(stack, c ? (int)strlen(c) : 0);
UNUSED_ARG(userdata);
}
#include "base36.h" #include "base36.h"
static void eval_int(opstack ** stack, const void *userdata) static void eval_int(opstack ** stack, const void *userdata)
{ {
int i = opop_i(stack); int i = opop_i(stack);
const char *c = itoa10(i); const char *c = itoa10(i);
size_t len = strlen(c); size_t size = strlen(c) + 1; /* Flawfinder: ignore */
variant var; variant var;
var.v = strcpy(balloc(len + 1), c); str_strlcpy(var.v = balloc(size), c, size);
opush(stack, var); opush(stack, var);
} }
@ -477,7 +476,6 @@ void translation_init(void)
add_function("eq", &eval_eq); add_function("eq", &eval_eq);
add_function("int", &eval_int); add_function("int", &eval_int);
add_function("add", &eval_add); add_function("add", &eval_add);
add_function("strlen", &eval_strlen);
add_function("if", &eval_if); add_function("if", &eval_if);
add_function("isnull", &eval_isnull); add_function("isnull", &eval_isnull);
} }

View file

@ -91,7 +91,7 @@ static int a_readdirection(variant *var, void *owner, struct gamedata *data)
{ {
struct storage *store = data->store; struct storage *store = data->store;
spec_direction *d = (spec_direction *)(var->v); spec_direction *d = (spec_direction *)(var->v);
char lbuf[32]; char lbuf[32]; /* Flawfinder: ignore */
(void)owner; (void)owner;
READ_INT(store, &d->x); READ_INT(store, &d->x);
@ -130,7 +130,7 @@ region *find_special_direction(const region * r, const char *token)
{ {
attrib *a; attrib *a;
if (strlen(token) == 0) if (*token == '\0')
return NULL; return NULL;
for (a = a_find(r->attribs, &at_direction); a && a->type == &at_direction; for (a = a_find(r->attribs, &at_direction); a && a->type == &at_direction;
a = a->next) { a = a->next) {