Simplified the combat code, removing battle::fighters and putting things in lists rather than vectors.

Removed the unnecessary shuffling and sorting that takes quite some time.
Fixed a few bugs in ally-selection, I think.
This commit is contained in:
Enno Rehling 2006-04-13 17:16:15 +00:00
parent 50b94b730d
commit 4d8ed2c854
5 changed files with 1567 additions and 1491 deletions

View File

@ -106,7 +106,7 @@ attack_firesword(const troop * at, const struct weapon_type * wtype, int *casual
} }
do { do {
dt = select_enemy(fi->side->battle, fi, minrow, maxrow, true); dt = select_enemy(fi, minrow, maxrow, true);
assert(dt.fighter); assert(dt.fighter);
--force; --force;
killed += terminate(dt, *at, AT_SPELL, damage, 1); killed += terminate(dt, *at, AT_SPELL, damage, 1);
@ -167,7 +167,7 @@ attack_catapult(const troop * at, const struct weapon_type * wtype, int * casual
while (--n >= 0) { while (--n >= 0) {
/* Select defender */ /* Select defender */
dt = select_enemy(b, af, minrow, maxrow, true); dt = select_enemy(af, minrow, maxrow, true);
if (!dt.fighter) if (!dt.fighter)
break; break;

File diff suppressed because it is too large Load Diff

View File

@ -19,8 +19,6 @@ extern "C" {
#define SHOW_KILLS #define SHOW_KILLS
#undef SMALL_BATTLE_MESSAGES #undef SMALL_BATTLE_MESSAGES
#undef FIXED_OPPONENTS
#undef NO_RUNNING
/** more defines **/ /** more defines **/
#define FS_ENEMY 1 #define FS_ENEMY 1
@ -29,6 +27,7 @@ extern "C" {
/***** Verteidigungslinien. /***** Verteidigungslinien.
* Eressea hat 4 Verteidigungslinien. 1 ist vorn, 5. enthält Summen * Eressea hat 4 Verteidigungslinien. 1 ist vorn, 5. enthält Summen
*/ */
#define NUMROWS 5 #define NUMROWS 5
#define SUM_ROW 0 #define SUM_ROW 0
#define FIGHT_ROW 1 #define FIGHT_ROW 1
@ -37,6 +36,7 @@ extern "C" {
#define FLEE_ROW 4 #define FLEE_ROW 4
#define LAST_ROW (NUMROWS-1) #define LAST_ROW (NUMROWS-1)
#define FIRST_ROW FIGHT_ROW #define FIRST_ROW FIGHT_ROW
#define MAXSIDES 256 /* if there are ever more than this, we're fucked. */
struct message; struct message;
@ -50,21 +50,24 @@ extern "C" {
boolean attacker; boolean attacker;
} bfaction; } bfaction;
typedef struct battle { typedef struct battle {
cvector leaders; cvector leaders;
struct region *region; struct region *region;
struct plane *plane; struct plane *plane;
bfaction * factions; bfaction * factions;
int nfactions; int nfactions;
cvector fighters; int nfighters;
cvector sides; #if 0
struct fighter ** fighters;
#endif
struct side * sides;
cvector meffects; cvector meffects;
int max_tactics; int max_tactics;
int turn; int turn;
boolean has_tactics_turn; boolean has_tactics_turn;
int keeploot; int keeploot;
boolean reelarrow; boolean reelarrow;
int dh;
int alive; int alive;
#ifdef SMALL_BATTLE_MESSAGES #ifdef SMALL_BATTLE_MESSAGES
boolean small; boolean small;
@ -76,17 +79,22 @@ extern "C" {
int value; int value;
} tactics; } tactics;
#define SIDE_STEALTH 1<<0
#ifdef SIMPLE_COMBAT
#define SIDE_ATTACKER 1<<1
#endif
typedef struct side { typedef struct side {
struct tactics leader; /* der beste Taktiker des Heeres */ struct side * next; /* nächstes Heer in der Schlacht */
struct side * nextF; /* nächstes Heer der gleichen Partei */ struct side * nextF; /* nächstes Heer der gleichen Partei */
struct battle * battle; struct battle * battle;
struct bfaction * bf; /* Die Partei, die hier kämpft */ struct bfaction * bf; /* Die Partei, die hier kämpft */
const struct group * group; const struct group * group;
struct tactics leader; /* der beste Taktiker des Heeres */
# define E_ENEMY 1 # define E_ENEMY 1
# define E_ATTACKING 2 # define E_ATTACKING 2
int enemy[128]; unsigned char enemy[128];
struct side * enemies[128]; struct side * enemies[128];
cvector fighters; /* vector der Einheiten dieser Fraktion */ struct fighter * fighters;
int index; /* Eintrag der Fraktion in b->matrix/b->enemies */ int index; /* Eintrag der Fraktion in b->matrix/b->enemies */
int size[NUMROWS]; /* Anzahl Personen in Reihe X. 0 = Summe */ int size[NUMROWS]; /* Anzahl Personen in Reihe X. 0 = Summe */
int nonblockers[NUMROWS]; /* Anzahl nichtblockierender Kämpfer, z.B. Schattenritter. */ int nonblockers[NUMROWS]; /* Anzahl nichtblockierender Kämpfer, z.B. Schattenritter. */
@ -96,8 +104,7 @@ extern "C" {
int dead; int dead;
int casualties; /* those dead that were real people, not undead! */ int casualties; /* those dead that were real people, not undead! */
int healed; int healed;
boolean dh; unsigned int flags;
boolean stealth; /* Die Einheiten sind getarnt */
const struct faction *stealthfaction; const struct faction *stealthfaction;
} side; } side;
@ -117,10 +124,6 @@ extern "C" {
#define FL_STUNNED 32 /* eine Runde keinen Angriff */ #define FL_STUNNED 32 /* eine Runde keinen Angriff */
#define FL_HIT 64 /* the person at attacked */ #define FL_HIT 64 /* the person at attacked */
/*** fighter::flags ***/
#define FIG_ATTACKED 1
#define FIG_NOLOOT 2
typedef struct troop { typedef struct troop {
struct fighter *fighter; struct fighter *fighter;
int index; int index;
@ -132,7 +135,11 @@ extern "C" {
int count; int count;
} armor; } armor;
/*** fighter::flags ***/
#define FIG_ATTACKER 1<<0
#define FIG_NOLOOT 1<<1
typedef struct fighter { typedef struct fighter {
struct fighter * next;
struct side *side; struct side *side;
struct unit *unit; /* Die Einheit, die hier kämpft */ struct unit *unit; /* Die Einheit, die hier kämpft */
struct building *building; /* Gebäude, in dem die Einheit evtl. steht */ struct building *building; /* Gebäude, in dem die Einheit evtl. steht */
@ -163,18 +170,13 @@ extern "C" {
int last_action : 4; /* In welcher Runde haben wir zuletzt etwas getan */ int last_action : 4; /* In welcher Runde haben wir zuletzt etwas getan */
struct weapon * missile; /* missile weapon */ struct weapon * missile; /* missile weapon */
struct weapon * melee; /* melee weapon */ struct weapon * melee; /* melee weapon */
#ifdef FIXED_OPPONENTS
struct troop opponent; /* default opponent */
#endif
} * person; } * person;
int flags; unsigned int flags;
struct { struct {
int number; /* number of people who have flown */ int number; /* number of people who have flown */
int hp; /* accumulated hp of fleeing people */ int hp; /* accumulated hp of fleeing people */
#ifndef NO_RUNNING
struct region *region; /* destination of fleeing people */ struct region *region; /* destination of fleeing people */
struct item * items; /* items they take */ struct item * items; /* items they take */
#endif
} run; } run;
#ifndef SIMPLE_COMBAT #ifndef SIMPLE_COMBAT
int action_counter; /* number of active actions the struct unit did in the fight */ int action_counter; /* number of active actions the struct unit did in the fight */
@ -208,7 +210,7 @@ extern "C" {
extern void do_battle(void); extern void do_battle(void);
/* for combar spells and special attacks */ /* for combar spells and special attacks */
extern troop select_enemy(struct battle * b, struct fighter * af, int minrow, int maxrow, boolean advance); extern troop select_enemy(struct fighter * af, int minrow, int maxrow, boolean advance);
extern int count_enemies(struct battle * b, struct side * as, int minrow, int maxrow, boolean advance); extern int count_enemies(struct battle * b, struct side * as, int minrow, int maxrow, boolean advance);
extern boolean terminate(troop dt, troop at, int type, const char *damage, boolean missile); extern boolean terminate(troop dt, troop at, int type, const char *damage, boolean missile);
extern void battlemsg(battle * b, struct unit * u, const char * s); extern void battlemsg(battle * b, struct unit * u, const char * s);
@ -218,7 +220,7 @@ extern "C" {
extern int hits(troop at, troop dt, weapon * awp); extern int hits(troop at, troop dt, weapon * awp);
extern void damage_building(struct battle *b, struct building *bldg, int damage_abs); extern void damage_building(struct battle *b, struct building *bldg, int damage_abs);
extern struct cvector * fighters(struct battle *b, struct fighter *af, int minrow, int maxrow, int mask); extern struct cvector * fighters(struct battle *b, struct fighter *af, int minrow, int maxrow, int mask);
extern int countallies(struct side * as); extern int count_allies(struct side * as, int minrow, int maxrow, boolean advance);
extern int get_unitrow(const struct fighter * af); extern int get_unitrow(const struct fighter * af);
extern boolean helping(struct side * as, struct side * ds); extern boolean helping(struct side * as, struct side * ds);
extern void rmfighter(fighter *df, int i); extern void rmfighter(fighter *df, int i);
@ -228,6 +230,7 @@ extern "C" {
extern int statusrow(int status); extern int statusrow(int status);
extern void drain_exp(struct unit *u, int d); extern void drain_exp(struct unit *u, int d);
extern void rmtroop(troop dt); extern void rmtroop(troop dt);
extern boolean is_attacker(const fighter * fig);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -152,7 +152,7 @@ sp_kampfzauber(fighter * fi, int level, double power, spell * sp)
} }
while (force>0 && killed < enemies) { while (force>0 && killed < enemies) {
dt = select_enemy(b, fi, minrow, maxrow, true); dt = select_enemy(fi, minrow, maxrow, true);
assert(dt.fighter); assert(dt.fighter);
--force; --force;
killed += terminate(dt, at, AT_COMBATSPELL, damage, false); killed += terminate(dt, at, AT_COMBATSPELL, damage, false);
@ -193,7 +193,7 @@ sp_versteinern(fighter * fi, int level, double power, spell * sp)
battlerecord(b, buf); battlerecord(b, buf);
while (force && stoned < enemies) { while (force && stoned < enemies) {
troop dt = select_enemy(b, fi, minrow, maxrow, true); troop dt = select_enemy(fi, minrow, maxrow, true);
fighter * df = dt.fighter; fighter * df = dt.fighter;
unit * du = df->unit; unit * du = df->unit;
if (is_magic_resistant(mage, du, 0) == false) { if (is_magic_resistant(mage, du, 0) == false) {
@ -253,7 +253,7 @@ sp_stun(fighter * fi, int level, double power, spell * sp)
stunned = 0; stunned = 0;
while (force && stunned < enemies) { while (force && stunned < enemies) {
troop dt = select_enemy(b, fi, minrow, maxrow, true); troop dt = select_enemy(fi, minrow, maxrow, true);
fighter * df = dt.fighter; fighter * df = dt.fighter;
unit * du = df->unit; unit * du = df->unit;
@ -395,7 +395,7 @@ sp_sleep(fighter * fi, int level, double power, spell * sp)
battlerecord(b, buf); battlerecord(b, buf);
while (force && enemies) { while (force && enemies) {
dt = select_enemy(b, fi, minrow, maxrow, true); dt = select_enemy(fi, minrow, maxrow, true);
assert(dt.fighter); assert(dt.fighter);
du = dt.fighter->unit; du = dt.fighter->unit;
if (is_magic_resistant(mage, du, 0) == false) { if (is_magic_resistant(mage, du, 0) == false) {
@ -414,35 +414,38 @@ sp_sleep(fighter * fi, int level, double power, spell * sp)
static troop static troop
select_ally_in_row(fighter * af, int minrow, int maxrow) select_ally(fighter * af, int minrow, int maxrow)
{ {
side *as = af->side; side *as = af->side;
battle *b = as->battle; battle *b = as->battle;
troop dt = no_troop; side * ds;
fighter *df; int allies = count_allies(as, minrow, maxrow, true);
int allies;
allies = countallies(as); if (!allies) {
return no_troop;
if (!allies) }
return dt;
allies = rng_int() % allies; allies = rng_int() % allies;
cv_foreach(df, b->fighters) { for (ds=b->sides; ds; ds=ds->next) {
side *ds = df->side; if (helping(as, ds)) {
fighter * df;
for (df=ds->fighters; df; df=df->next) {
int dr = get_unitrow(df); int dr = get_unitrow(df);
if (dr >= minrow && dr <= maxrow) {
if (helping(as, ds) && dr >= minrow && dr <= maxrow) {
if (df->alive - df->removed > allies) { if (df->alive - df->removed > allies) {
troop dt;
assert(allies>=0);
dt.index = allies; dt.index = allies;
dt.fighter = df; dt.fighter = df;
break; return dt;
} }
allies -= df->alive; allies -= df->alive;
} }
} }
cv_next(df); }
return dt; }
assert(!"we should never have gotten here");
return no_troop;
} }
int int
@ -463,13 +466,13 @@ sp_speed(fighter * fi, int level, double power, spell * sp)
force = lovar(power * power * 5); force = lovar(power * power * 5);
allies = countallies(fi->side); allies = count_allies(fi->side, minrow, maxrow, true);
/* maximal 2*allies Versuche ein Opfer zu finden, ansonsten bestände /* maximal 2*allies Versuche ein Opfer zu finden, ansonsten bestände
* die Gefahr eine Endlosschleife*/ * die Gefahr eine Endlosschleife*/
allies *= 2; allies *= 2;
while (force && allies) { while (force && allies) {
troop dt = select_ally_in_row(fi, minrow, maxrow); troop dt = select_ally(fi, minrow, maxrow);
fighter *df = dt.fighter; fighter *df = dt.fighter;
--allies; --allies;
@ -541,7 +544,7 @@ sp_mindblast(fighter * fi, int level, double power, spell * sp)
battlerecord(b, buf); battlerecord(b, buf);
while (force && enemies) { while (force && enemies) {
dt = select_enemy(b, fi, minrow, maxrow, true); dt = select_enemy(fi, minrow, maxrow, true);
assert(dt.fighter); assert(dt.fighter);
du = dt.fighter->unit; du = dt.fighter->unit;
if (humanoidrace(du->race) && !is_magic_resistant(mage, du, 0)) { if (humanoidrace(du->race) && !is_magic_resistant(mage, du, 0)) {
@ -615,7 +618,7 @@ sp_dragonodem(fighter * fi, int level, double power, spell * sp)
at.index = 0; at.index = 0;
while (force && killed < enemies) { while (force && killed < enemies) {
dt = select_enemy(b, fi, minrow, maxrow, true); dt = select_enemy(fi, minrow, maxrow, true);
assert(dt.fighter); assert(dt.fighter);
--force; --force;
killed += terminate(dt, at, AT_COMBATSPELL, damage, false); killed += terminate(dt, at, AT_COMBATSPELL, damage, false);
@ -724,7 +727,7 @@ sp_drainodem(fighter * fi, int level, double power, spell * sp)
at.index = 0; at.index = 0;
while (force && drained < enemies) { while (force && drained < enemies) {
dt = select_enemy(b, fi, minrow, maxrow, true); dt = select_enemy(fi, minrow, maxrow, true);
assert(dt.fighter); assert(dt.fighter);
if (hits(at, dt, NULL)) { if (hits(at, dt, NULL)) {
drain_exp(dt.fighter->unit, 90); drain_exp(dt.fighter->unit, 90);
@ -772,7 +775,7 @@ sp_shadowcall(fighter * fi, int level, double power, spell * sp)
a->data.ca[1] = 100; a->data.ca[1] = 100;
a_add(&u->attribs, a); a_add(&u->attribs, a);
make_fighter(b, u, fi->side, fval(fi, FIG_ATTACKED)); make_fighter(b, u, fi->side, is_attacker(fi));
sprintf(buf, "%s ruft %d %s zu Hilfe", unitname(mage), force, sprintf(buf, "%s ruft %d %s zu Hilfe", unitname(mage), force,
racename(default_locale, u, u->race)); racename(default_locale, u, u->race));
battlerecord(b, buf); battlerecord(b, buf);
@ -805,7 +808,7 @@ sp_wolfhowl(fighter * fi, int level, double power, spell * sp)
a->data.ca[1] = 100; a->data.ca[1] = 100;
a_add(&u->attribs, a); a_add(&u->attribs, a);
make_fighter(b, u, fi->side, fval(fi, FIG_ATTACKED)); make_fighter(b, u, fi->side, is_attacker(fi));
sprintf(buf, "%s ruft %d %s zu Hilfe", unitname(mage), force, sprintf(buf, "%s ruft %d %s zu Hilfe", unitname(mage), force,
racename(default_locale, u, u->race)); racename(default_locale, u, u->race));
battlerecord(b, buf); battlerecord(b, buf);
@ -838,7 +841,7 @@ sp_shadowknights(fighter * fi, int level, double power, spell * sp)
a->data.ca[1] = 100; a->data.ca[1] = 100;
a_add(&u->attribs, a); a_add(&u->attribs, a);
make_fighter(b, u, fi->side, fval(fi, FIG_ATTACKED)); make_fighter(b, u, fi->side, is_attacker(fi));
sprintf(buf, "%s beschwört Trugbilder herauf", unitname(mage)); sprintf(buf, "%s beschwört Trugbilder herauf", unitname(mage));
battlerecord(b, buf); battlerecord(b, buf);
@ -1071,13 +1074,13 @@ sp_hero(fighter * fi, int level, double power, spell * sp)
scat(":"); scat(":");
battlerecord(b, buf); battlerecord(b, buf);
allies = countallies(fi->side); allies = count_allies(fi->side, minrow, maxrow, true);
/* maximal 2*allies Versuche ein Opfer zu finden, ansonsten bestände /* maximal 2*allies Versuche ein Opfer zu finden, ansonsten bestände
* die Gefahr eine Endlosschleife*/ * die Gefahr eine Endlosschleife*/
allies *= 2; allies *= 2;
while (force && allies) { while (force && allies) {
troop dt = select_ally_in_row(fi, minrow, maxrow); troop dt = select_ally(fi, minrow, maxrow);
fighter *df = dt.fighter; fighter *df = dt.fighter;
--allies; --allies;
@ -1131,13 +1134,13 @@ sp_berserk(fighter * fi, int level, double power, spell * sp)
scat(":"); scat(":");
battlerecord(b, buf); battlerecord(b, buf);
allies = countallies(fi->side); allies = count_allies(fi->side, minrow, maxrow, true);
/* maximal 2*allies Versuche ein Opfer zu finden, ansonsten bestände /* maximal 2*allies Versuche ein Opfer zu finden, ansonsten bestände
* die Gefahr eine Endlosschleife*/ * die Gefahr eine Endlosschleife*/
allies *= 2; allies *= 2;
while (force && allies) { while (force && allies) {
troop dt = select_ally_in_row(fi, minrow, maxrow); troop dt = select_ally(fi, minrow, maxrow);
fighter *df = dt.fighter; fighter *df = dt.fighter;
--allies; --allies;
@ -1190,7 +1193,7 @@ sp_frighten(fighter * fi, int level, double power, spell * sp)
battlerecord(b, buf); battlerecord(b, buf);
while (force && enemies) { while (force && enemies) {
troop dt = select_enemy(b, fi, minrow, maxrow, true); troop dt = select_enemy(fi, minrow, maxrow, true);
fighter *df = dt.fighter; fighter *df = dt.fighter;
--enemies; --enemies;
@ -1236,7 +1239,7 @@ sp_tiredsoldiers(fighter * fi, int level, double power, spell * sp)
} }
while (force) { while (force) {
troop t = select_enemy(b, fi, FIGHT_ROW, BEHIND_ROW, true); troop t = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, true);
fighter *df = t.fighter; fighter *df = t.fighter;
if (!df) if (!df)
@ -1297,7 +1300,7 @@ sp_windshield(fighter * fi, int level, double power, spell * sp)
} }
while (force && enemies) { while (force && enemies) {
troop dt = select_enemy(b, fi, minrow, maxrow, true); troop dt = select_enemy(fi, minrow, maxrow, true);
fighter *df = dt.fighter; fighter *df = dt.fighter;
--enemies; --enemies;
@ -1355,7 +1358,7 @@ sp_denyattack(fighter * fi, int level, double power, spell * sp)
/* und bewachen nicht */ /* und bewachen nicht */
setguard(mage, GUARD_NONE); setguard(mage, GUARD_NONE);
/* irgendwie den langen befehl sperren */ /* irgendwie den langen befehl sperren */
fset(fi, FIG_ATTACKED); /* fset(fi, FIG_ATTACKED); */
/* Hat der Magier ein NACH, wird die angegebene Richtung bevorzugt */ /* Hat der Magier ein NACH, wird die angegebene Richtung bevorzugt */
switch (get_keyword(mage->thisorder)) { switch (get_keyword(mage->thisorder)) {
@ -1495,11 +1498,11 @@ count_healable(battle *b, fighter *df)
side *s; side *s;
int healable = 0; int healable = 0;
cv_foreach(s, b->sides) { for (s=b->sides; s; s=s->next) {
if (helping(df->side, s)) { if (helping(df->side, s)) {
healable += s->casualties; healable += s->casualties;
} }
} cv_next(s); }
return healable; return healable;
} }

View File

@ -21,7 +21,6 @@ Code cleanup:
Larger Features: Larger Features:
- eressea (b/g)zip reports? - eressea (b/g)zip reports?
- NO_RUNNING
- ZERSTÖRE - Man sollte alle Materialien zurückkriegen können: - ZERSTÖRE - Man sollte alle Materialien zurückkriegen können:
Scripts, etc: Scripts, etc: