"buildings and ships are leaking memory"
- remove_building and remove_ship work like their region/unit counterparts
This commit is contained in:
Enno Rehling 2008-05-23 09:25:41 +00:00
parent 43d73a6b45
commit f0c56346d9
18 changed files with 206 additions and 180 deletions

View File

@ -978,41 +978,41 @@ maintain(building * b, boolean first)
static void static void
gebaeude_stuerzt_ein(region * r, building * b) gebaeude_stuerzt_ein(region * r, building * b)
{ {
unit *u; unit *u;
int n, i; int n, i;
int opfer = 0; int opfer = 0;
int road = 0; int road = 0;
struct message * msg; struct message * msg;
for (u = r->units; u; u = u->next) { for (u = r->units; u; u = u->next) {
if (u->building == b) { if (u->building == b) {
int loss = 0; int loss = 0;
fset(u->faction, FFL_MARK); fset(u->faction, FFL_MARK);
freset(u, UFL_OWNER); freset(u, UFL_OWNER);
leave(r,u); leave(r,u);
n = u->number; n = u->number;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (rng_double() >= COLLAPSE_SURVIVAL) { if (rng_double() >= COLLAPSE_SURVIVAL) {
++loss; ++loss;
} }
} }
scale_number(u, u->number - loss); scale_number(u, u->number - loss);
opfer += loss; opfer += loss;
} }
} }
msg = msg_message("buildingcrash", "region building opfer road", r, b, opfer, road); msg = msg_message("buildingcrash", "region building opfer road", r, b, opfer, road);
add_message(&r->msgs, msg); add_message(&r->msgs, msg);
for (u=r->units; u; u=u->next) { for (u=r->units; u; u=u->next) {
faction * f = u->faction; faction * f = u->faction;
if (fval(f, FFL_MARK)) { if (fval(f, FFL_MARK)) {
freset(u->faction, FFL_MARK); freset(u->faction, FFL_MARK);
add_message(&f->msgs, msg); add_message(&f->msgs, msg);
} }
} }
msg_release(msg); msg_release(msg);
destroy_building(b); remove_building(&r->buildings, b);
} }
void void

View File

@ -2485,7 +2485,7 @@ sinkships(region * r)
damage_ship(sh, 0.05); damage_ship(sh, 0.05);
} }
if (sh->damage >= sh->size * DAMAGE_SCALE) { if (sh->damage >= sh->size * DAMAGE_SCALE) {
destroy_ship(sh); remove_ship(shp, sh);
} }
if (*shp==sh) shp=&sh->next; if (*shp==sh) shp=&sh->next;
} }

View File

@ -427,7 +427,6 @@ void
chaos(region * r) chaos(region * r)
{ {
unit *u = NULL, *u2; unit *u = NULL, *u2;
building *b, *b2;
if (rng_int() % 100 < 8) { if (rng_int() % 100 < 8) {
switch (rng_int() % 3) { switch (rng_int() % 3) {
@ -474,7 +473,9 @@ chaos(region * r)
while (sh) { while (sh) {
ship * nsh = sh->next; ship * nsh = sh->next;
damage_ship(sh, 0.50); damage_ship(sh, 0.50);
if (sh->damage >= sh->size * DAMAGE_SCALE) destroy_ship(sh); if (sh->damage >= sh->size * DAMAGE_SCALE) {
remove_ship(&sh->region->ships, sh);
}
sh = nsh; sh = nsh;
} }
@ -487,10 +488,8 @@ chaos(region * r)
} }
ADDMSG(&r->msgs, msg_message("tidalwave", "region", r)); ADDMSG(&r->msgs, msg_message("tidalwave", "region", r));
for (b = rbuildings(r); b;) { while (r->buildings) {
b2 = b->next; remove_building(&r->buildings, r->buildings);
destroy_building(b);
b = b2;
} }
terraform(r, T_OCEAN); terraform(r, T_OCEAN);
} }
@ -760,7 +759,6 @@ melt_iceberg(region *r)
{ {
attrib *a; attrib *a;
unit *u; unit *u;
building *b, *b2;
for (u=r->units; u; u=u->next) freset(u->faction, FFL_SELECT); for (u=r->units; u; u=u->next) freset(u->faction, FFL_SELECT);
for (u=r->units; u; u=u->next) if (!fval(u->faction, FFL_SELECT)) { for (u=r->units; u; u=u->next) if (!fval(u->faction, FFL_SELECT)) {
@ -773,10 +771,9 @@ melt_iceberg(region *r)
if (a) a_remove(&r->attribs, a); if (a) a_remove(&r->attribs, a);
/* Gebäude löschen */ /* Gebäude löschen */
for (b = rbuildings(r); b; b = b2) { while (r->buildings) {
b2 = b->next; remove_building(&r->buildings, r->buildings);
destroy_building(b); }
}
/* in Ozean wandeln */ /* in Ozean wandeln */
terraform(r, T_OCEAN); terraform(r, T_OCEAN);
@ -875,7 +872,7 @@ move_iceberg(region *r)
ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg_des", ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg_des",
"ship", sh)); "ship", sh));
} }
destroy_ship(sh); remove_ship(&sh->region->ships, sh);
} else if (u!=NULL) { } else if (u!=NULL) {
ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg", ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg",
"ship", sh)); "ship", sh));
@ -985,7 +982,7 @@ godcurse(void)
unit * u = shipowner(sh); unit * u = shipowner(sh);
if (u) ADDMSG(&u->faction->msgs, if (u) ADDMSG(&u->faction->msgs,
msg_message("godcurse_destroy_ship", "ship", sh)); msg_message("godcurse_destroy_ship", "ship", sh));
destroy_ship(sh); remove_ship(&sh->region->ships, sh);
} }
sh = shn; sh = shn;
} }
@ -1122,11 +1119,10 @@ void
randomevents(void) randomevents(void)
{ {
#if KARMA_MODULE #if KARMA_MODULE
faction *f; faction *f;
#endif /* KARMA_MODULE */ #endif /* KARMA_MODULE */
region *r; region *r;
building *b, *b2; unit *u;
unit *u;
icebergs(); icebergs();
godcurse(); godcurse();
@ -1191,14 +1187,16 @@ randomevents(void)
/* Monumente zerfallen, Schiffe verfaulen */ /* Monumente zerfallen, Schiffe verfaulen */
for (r = regions; r; r = r->next) { for (r = regions; r; r = r->next) {
for (b = rbuildings(r); b; b = b2) { building ** blist = &r->buildings;
b2 = b->next; while (*blist) {
building * b = *blist;
if (fval(b->type, BTF_DECAY) && !buildingowner(r, b)) { if (fval(b->type, BTF_DECAY) && !buildingowner(r, b)) {
b->size -= max(1, (b->size * 20) / 100); b->size -= max(1, (b->size * 20) / 100);
if (b->size == 0) { if (b->size == 0) {
destroy_building(b); remove_building(blist, r->buildings);
} }
} }
if (*blist==b) blist=&b->next;
} }
} }
@ -1213,7 +1211,7 @@ randomevents(void)
"unit region", u, r)); "unit region", u, r));
u_setfaction(u, get_monsters()); u_setfaction(u, get_monsters());
} }
} }
} }
} }
@ -1226,7 +1224,7 @@ randomevents(void)
for(u = f->units; u; u=u->nextF) { for(u = f->units; u; u=u->nextF) {
if (rng_int()%100 < 2*level) { if (rng_int()%100 < 2*level) {
ADDMSG(&u->faction->msgs, ADDMSG(&u->faction->msgs,
msg_message("becomewere", "unit region", u, u->region)); msg_message("becomewere", "unit region", u, u->region));
fset(u, UFL_WERE); fset(u, UFL_WERE);
} }
} }

View File

@ -566,7 +566,7 @@ sink_ship(region * r, ship * sh, const char *name, char spy, unit * saboteur)
if (enemy_discovers_spy_msg) msg_release(enemy_discovers_spy_msg); if (enemy_discovers_spy_msg) msg_release(enemy_discovers_spy_msg);
if (sink_msg) msg_release(sink_msg); if (sink_msg) msg_release(sink_msg);
/* finally, get rid of the ship */ /* finally, get rid of the ship */
destroy_ship(sh); remove_ship(&sh->region->ships, sh);
vset_destroy(&informed); vset_destroy(&informed);
vset_destroy(&survivors); vset_destroy(&survivors);
} }

View File

@ -2572,7 +2572,7 @@ aftermath(battle * b)
ship * sh = *sp; ship * sh = *sp;
freset(sh, SF_DAMAGED); freset(sh, SF_DAMAGED);
if (sh->damage >= sh->size * DAMAGE_SCALE) { if (sh->damage >= sh->size * DAMAGE_SCALE) {
destroy_ship(sh); remove_ship(sp, sh);
} }
if (*sp==sh) sp=&sh->next; if (*sp==sh) sp=&sh->next;
} }

View File

@ -384,7 +384,7 @@ destroy_cmd(unit * u, struct order * ord)
ADDMSG(&u->faction->msgs, msg_message("destroy", ADDMSG(&u->faction->msgs, msg_message("destroy",
"building unit", b, u)); "building unit", b, u));
con = b->type->construction; con = b->type->construction;
destroy_building(b); remove_building(&r->buildings, b);
} else { } else {
/* partial destroy */ /* partial destroy */
b->size -= n; b->size -= n;
@ -411,7 +411,7 @@ destroy_cmd(unit * u, struct order * ord)
ADDMSG(&u->faction->msgs, msg_message("shipdestroy", ADDMSG(&u->faction->msgs, msg_message("shipdestroy",
"unit region ship", u, r, sh)); "unit region ship", u, r, sh));
con = sh->type->construction; con = sh->type->construction;
destroy_ship(sh); remove_ship(&sh->region->ships, sh);
} else { } else {
/* partial destroy */ /* partial destroy */
sh->size -= (sh->type->construction->maxsize * n)/100; sh->size -= (sh->type->construction->maxsize * n)/100;

View File

@ -394,7 +394,7 @@ read_building_reference(struct building ** b, struct storage * store)
*b = findbuilding(var.i); *b = findbuilding(var.i);
if (*b==NULL) ur_add(var, (void**)b, resolve_building); if (*b==NULL) ur_add(var, (void**)b, resolve_building);
return AT_READ_OK; return AT_READ_OK;
} }
} }
void void
@ -452,8 +452,13 @@ new_building(const struct building_type * btype, region * r, const struct locale
return b; return b;
} }
static building * deleted_buildings;
/** remove a building from the region.
* remove_building lets units leave the building
*/
void void
destroy_building(building * b) remove_building(building ** blist, building * b)
{ {
unit *u; unit *u;
direction_t d; direction_t d;
@ -467,7 +472,9 @@ destroy_building(building * b)
bt_tunnel = bt_find("tunnel"); bt_tunnel = bt_find("tunnel");
} }
if (!bfindhash(b->no)) return; assert(bfindhash(b->no));
handle_event(b->attribs, "destroy", b);
for (u=b->region->units; u; u=u->next) { for (u=b->region->units; u; u=u->next) {
if (u->building == b) leave(b->region, u); if (u->building == b) leave(b->region, u);
} }
@ -486,8 +493,29 @@ destroy_building(building * b)
} }
/* Stattdessen nur aus Liste entfernen, aber im Speicher halten. */ /* Stattdessen nur aus Liste entfernen, aber im Speicher halten. */
choplist(&b->region->buildings, b); while (*blist && *blist!=b) blist = &(*blist)->next;
handle_event(b->attribs, "destroy", b); *blist = b->next;
b->region = NULL;
b->next = deleted_buildings;
deleted_buildings = b;
}
void
free_building(building * b)
{
while (b->attribs) a_remove (&b->attribs, b->attribs);
free(b->name);
free(b->display);
free(b);
}
void
free_buildings(void)
{
while (deleted_buildings) {
building * b = deleted_buildings;
deleted_buildings = b->next;
}
} }
extern struct attrib_type at_icastle; extern struct attrib_type at_icastle;

View File

@ -123,7 +123,10 @@ int buildingeffsize(const building * b, boolean img);
void bhash(struct building * b); void bhash(struct building * b);
void bunhash(struct building * b); void bunhash(struct building * b);
int buildingcapacity(const struct building * b); int buildingcapacity(const struct building * b);
void destroy_building(struct building * b);
extern void remove_building(struct building * *blist, struct building * b);
extern void free_building(struct building * b);
extern void free_buildings(void);
const struct building_type * findbuildingtype(const char * name, const struct locale * lang); const struct building_type * findbuildingtype(const char * name, const struct locale * lang);

View File

@ -144,17 +144,17 @@ a_writeicastle(const attrib * a, struct storage * store)
static int static int
a_ageicastle(struct attrib * a) a_ageicastle(struct attrib * a)
{ {
icastle_data * data = (icastle_data*)a->data.v; icastle_data * data = (icastle_data*)a->data.v;
if (data->time<=0) { if (data->time<=0) {
building * b = data->building; building * b = data->building;
region * r = b->region; region * r = b->region;
ADDMSG(&r->msgs, msg_message("icastle_dissolve", "building", b)); ADDMSG(&r->msgs, msg_message("icastle_dissolve", "building", b));
/* destroy_building lets units leave the building */ /* remove_building lets units leave the building */
destroy_building(b); remove_building(&r->buildings, b);
return 0; return 0;
} }
else data->time--; else data->time--;
return 1; return 1;
} }
static void static void

View File

@ -481,23 +481,24 @@ static ship *
do_maelstrom(region *r, unit *u) do_maelstrom(region *r, unit *u)
{ {
int damage; int damage;
ship * sh = u->ship;
damage = rng_int()%150 - eff_skill(u, SK_SAILING, r)*5; damage = rng_int()%150 - eff_skill(u, SK_SAILING, r)*5;
if (damage <= 0) { if (damage <= 0) {
return u->ship; return sh;
} }
damage_ship(u->ship, 0.01*damage); damage_ship(u->ship, 0.01*damage);
if (u->ship->damage >= u->ship->size * DAMAGE_SCALE) { if (sh->damage >= sh->size * DAMAGE_SCALE) {
ADDMSG(&u->faction->msgs, msg_message("entermaelstrom", ADDMSG(&u->faction->msgs, msg_message("entermaelstrom",
"region ship damage sink", r, u->ship, damage, 1)); "region ship damage sink", r, sh, damage, 1));
destroy_ship(u->ship); remove_ship(&sh->region->ships, sh);
return NULL; return NULL;
} }
ADDMSG(&u->faction->msgs, msg_message("entermaelstrom", ADDMSG(&u->faction->msgs, msg_message("entermaelstrom",
"region ship damage sink", r, u->ship, damage, 0)); "region ship damage sink", r, sh, damage, 0));
return u->ship; return u->ship;
} }
@ -776,7 +777,7 @@ drifting_ships(region * r)
damage_ship(sh, 0.02); damage_ship(sh, 0.02);
if (sh->damage>=sh->size * DAMAGE_SCALE) { if (sh->damage>=sh->size * DAMAGE_SCALE) {
destroy_ship(sh); remove_ship(shp, sh);
} }
} }
@ -1782,7 +1783,7 @@ sail(unit * u, order * ord, boolean move_on_land, region_list **routep)
if (sh->damage>=sh->size * DAMAGE_SCALE) { if (sh->damage>=sh->size * DAMAGE_SCALE) {
ADDMSG(&f->msgs, msg_message("shipsink", "ship", sh)); ADDMSG(&f->msgs, msg_message("shipsink", "ship", sh));
destroy_ship(sh); remove_ship(&sh->region->ships, sh);
sh = NULL; sh = NULL;
} }
@ -2322,7 +2323,7 @@ destroy_damaged_ships(void)
for(sh=r->ships;sh;) { for(sh=r->ships;sh;) {
shn = sh->next; shn = sh->next;
if (sh->damage>=sh->size * DAMAGE_SCALE) { if (sh->damage>=sh->size * DAMAGE_SCALE) {
destroy_ship(sh); remove_ship(&sh->region->ships, sh);
} }
sh = shn; sh = shn;
} }

View File

@ -951,19 +951,15 @@ free_region(region * r)
while (r->buildings) { while (r->buildings) {
building * b = r->buildings; building * b = r->buildings;
r->buildings = b->next; r->buildings = b->next;
bunhash(b); bunhash(b); /* must be done here, because remove_building does it, and wasn't called */
free(b->name); free_building(b);
free(b->display);
free(b);
} }
while (r->ships) { while (r->ships) {
ship * s = r->ships; ship * s = r->ships;
r->ships = s->next; r->ships = s->next;
sunhash(s); sunhash(s);
free(s->name); free_ship(s);
free(s->display);
free(s);
} }
free(r); free(r);

View File

@ -24,6 +24,7 @@
#include "skill.h" #include "skill.h"
/* util includes */ /* util includes */
#include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/event.h> #include <util/event.h>
#include <util/language.h> #include <util/language.h>
@ -162,32 +163,33 @@ captain(ship *sh, region *r)
} }
/* Alte Schiffstypen: */ /* Alte Schiffstypen: */
static ship * deleted_ships;
ship * ship *
new_ship(const ship_type * stype, const struct locale * lang, region * r) new_ship(const ship_type * stype, const struct locale * lang, region * r)
{ {
static char buffer[7 + IDSIZE + 1]; static char buffer[7 + IDSIZE + 1];
ship *sh = (ship *) calloc(1, sizeof(ship)); ship *sh = (ship *) calloc(1, sizeof(ship));
sh->no = newcontainerid(); sh->no = newcontainerid();
sh->coast = NODIRECTION; sh->coast = NODIRECTION;
sh->type = stype; sh->type = stype;
sh->region = r; sh->region = r;
sprintf(buffer, "%s %s", LOC(lang, stype->name[0]), shipid(sh)); sprintf(buffer, "%s %s", LOC(lang, stype->name[0]), shipid(sh));
sh->name = strdup(buffer); sh->name = strdup(buffer);
shash(sh); shash(sh);
addlist(&r->ships, sh); addlist(&r->ships, sh);
return sh; return sh;
} }
void void
destroy_ship(ship * sh) remove_ship(ship ** slist, ship * sh)
{ {
region * r = sh->region; region * r = sh->region;
unit * u = r->units; unit * u = r->units;
handle_event(sh->attribs, "destroy", sh);
while (u) { while (u) {
if (u->ship == sh) { if (u->ship == sh) {
leave_ship(u); leave_ship(u);
@ -195,8 +197,28 @@ destroy_ship(ship * sh)
u = u->next; u = u->next;
} }
sunhash(sh); sunhash(sh);
choplist(&r->ships, sh); while (*slist && *slist!=sh) slist = &(*slist)->next;
handle_event(sh->attribs, "destroy", sh); *slist = sh->next;
sh->next = deleted_ships;
deleted_ships = sh;
}
void
free_ship(ship * s)
{
while (s->attribs) a_remove(&s->attribs, s->attribs);
free(s->name);
free(s->display);
free(s);
}
void
free_ships(void)
{
while (deleted_ships) {
ship * s = deleted_ships;
deleted_ships = s->next;
}
} }
const char * const char *

View File

@ -97,7 +97,10 @@ extern const struct ship_type * findshiptype(const char *s, const struct locale
extern void register_ships(void); extern void register_ships(void);
extern void write_ship_reference(const struct ship * sh, struct storage * store); extern void write_ship_reference(const struct ship * sh, struct storage * store);
extern void destroy_ship(struct ship * s); extern void remove_ship(struct ship ** slist, struct ship * s);
extern void free_ship(struct ship * s);
extern void free_ships(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -23,10 +23,12 @@
#include <kernel/plane.h> #include <kernel/plane.h>
#include <kernel/region.h> #include <kernel/region.h>
#include <kernel/unit.h> #include <kernel/unit.h>
#include <kernel/version.h>
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/rng.h> #include <util/rng.h>
#include <util/resolve.h>
#include <util/storage.h> #include <util/storage.h>
/* libc includes */ /* libc includes */
@ -51,7 +53,7 @@ cmp_age(const void * v1, const void *v2)
typedef struct wormhole_data { typedef struct wormhole_data {
building * entry; building * entry;
building * exit; region * exit;
} wormhole_data; } wormhole_data;
static void static void
@ -80,10 +82,10 @@ wormhole_age(struct attrib * a)
if (u->number>maxtransport || has_limited_skills(u)) { if (u->number>maxtransport || has_limited_skills(u)) {
m = msg_message("wormhole_requirements", "unit region", u, u->region); m = msg_message("wormhole_requirements", "unit region", u, u->region);
} else if (data->exit!=NULL) { } else if (data->exit!=NULL) {
move_unit(u, data->exit->region, NULL); move_unit(u, data->exit, NULL);
maxtransport -= u->number; maxtransport -= u->number;
m = msg_message("wormhole_exit", "unit region", u, data->exit->region); m = msg_message("wormhole_exit", "unit region", u, data->exit);
add_message(&data->exit->region->msgs, m); add_message(&data->exit->msgs, m);
} }
if (m!=NULL) { if (m!=NULL) {
add_message(&u->faction->msgs, m); add_message(&u->faction->msgs, m);
@ -92,11 +94,8 @@ wormhole_age(struct attrib * a)
} }
} }
/* it's important that destroy_building doesn't change b->region, because remove_building(&r->buildings, data->entry);
* otherwise the tunnel would no longer be bi-directional after this */
destroy_building(data->entry);
ADDMSG(&r->msgs, msg_message("wormhole_dissolve", "region", r)); ADDMSG(&r->msgs, msg_message("wormhole_dissolve", "region", r));
assert(data->entry->region==r);
/* age returns 0 if the attribute needs to be removed, !=0 otherwise */ /* age returns 0 if the attribute needs to be removed, !=0 otherwise */
return -1; return -1;
@ -140,8 +139,10 @@ make_wormhole(const building_type * bt_wormhole, region * r1, region * r2)
attrib * a2 = a_add(&b2->attribs, a_new(&at_wormhole)); attrib * a2 = a_add(&b2->attribs, a_new(&at_wormhole));
wormhole_data * d1 = (wormhole_data*)a1->data.v; wormhole_data * d1 = (wormhole_data*)a1->data.v;
wormhole_data * d2 = (wormhole_data*)a2->data.v; wormhole_data * d2 = (wormhole_data*)a2->data.v;
d1->entry = d2->exit = b1; d1->entry = b1;
d2->entry = d1->exit = b2; d2->entry = b2;
d1->exit = b2->region;
d2->exit = b1->region;
b1->size = bt_wormhole->maxsize; b1->size = bt_wormhole->maxsize;
b2->size = bt_wormhole->maxsize; b2->size = bt_wormhole->maxsize;
ADDMSG(&r1->msgs, msg_message("wormhole_appear", "region", r1)); ADDMSG(&r1->msgs, msg_message("wormhole_appear", "region", r1));

View File

@ -1604,7 +1604,6 @@ destroy_all_roads(region *r)
static int static int
sp_great_drought(castorder *co) sp_great_drought(castorder *co)
{ {
building *b, *b2;
unit *u; unit *u;
boolean terraform = false; boolean terraform = false;
region *r = co->rt; region *r = co->rt;
@ -1664,10 +1663,8 @@ sp_great_drought(castorder *co)
set_number(u, 0); set_number(u, 0);
} }
} }
for (b = r->buildings; b;) { while (r->buildings) {
b2 = b->next; remove_building(&r->buildings, r->buildings);
destroy_building(b);
b = b2;
} }
} }
break; break;
@ -2271,39 +2268,28 @@ static int
sp_earthquake(castorder *co) sp_earthquake(castorder *co)
{ {
int kaputt; int kaputt;
building *burg;
unit *u;
region *r = co->rt; region *r = co->rt;
unit *mage = co->magician.u; unit *mage = co->magician.u;
int cast_level = co->level; int cast_level = co->level;
message * msg; message * msg;
building **blist = &r->buildings;
for (burg = r->buildings; burg; burg = burg->next) { while (*blist) {
if (burg->size == 0 ) building * burg = *blist;
continue;
/* Schutzzauber */ if (burg->size != 0 && !is_cursed(burg->attribs, C_MAGICWALLS, 0)) {
if (is_cursed(burg->attribs, C_MAGICWALLS, 0)) /* Magieresistenz */
continue; if (!target_resists_magic(mage, burg, TYP_BUILDING, 0)) {
kaputt = min(10 * cast_level, burg->size / 4);
/* Magieresistenz */ kaputt = max(kaputt, 1);
if (target_resists_magic(mage, burg, TYP_BUILDING, 0)) burg->size -= kaputt;
continue; if (burg->size == 0) {
/* TODO: sollten die Insassen nicht Schaden nehmen? */
kaputt = min(10 * cast_level, burg->size / 4); remove_building(blist, burg);
kaputt = max(kaputt, 1);
burg->size -= kaputt;
if (burg->size == 0 ) {
/* alle Einheiten hinausbefördern */
for(u = r->units; u; u = u->next ) {
if (u->building == burg ) {
u->building = 0;
freset(u, UFL_OWNER);
} }
} }
/* TODO: sollten die Insassen nicht Schaden nehmen? */
destroy_building(burg);
} }
if (*blist==burg) blist=&burg->next;
} }
/* melden, 1x pro Partei */ /* melden, 1x pro Partei */
@ -3198,11 +3184,16 @@ dc_read_compat(struct attrib * a, storage * store)
variant var; variant var;
int duration = store->r_int(store); int duration = store->r_int(store);
double strength = store->r_flt(store); double strength = store->r_flt(store);
short rx, ry;
var.i = store->r_id(store); var.i = store->r_id(store);
u = findunit(var.i); u = findunit(var.i);
read_region_reference(&r, store); /* this only affects really old data. no need to change: */
rx = store->r_int(store);
ry = store->r_int(store);
r = findregion(rx, ry);
if (r!=NULL) { if (r!=NULL) {
variant effect; variant effect;
curse * c; curse * c;

View File

@ -87,16 +87,6 @@ insertlist(void_list ** l, void_list * p)
} }
void
promotelist(void *l, void *p)
{
/* remove entry p from list l; insert p again at the beginning of l */
choplist(l, p);
insertlist((void_list **)l, (void_list *)p);
}
void void
removelist(void *l, void *p) removelist(void *l, void *p)
{ {
@ -124,21 +114,6 @@ freelist(void *p1)
} }
} }
void
invert_list(void * heap)
{
void_list * x = NULL;
void_list * m = *(void_list**)heap;
while (m)
{
void_list * d = m;
m = m->next;
d->next = x;
x = d;
}
*(void **)heap = x;
}
unsigned int unsigned int
listlen(void *l) listlen(void *l)
{ {

View File

@ -39,7 +39,6 @@ typedef struct void_list {
void addlist(void *l1, void *p1); void addlist(void *l1, void *p1);
void choplist(void * l, void * p); void choplist(void * l, void * p);
void translist(void *l1, void *l2, void *p); void translist(void *l1, void *l2, void *p);
void promotelist(void *l, void *p);
#ifndef MALLOCDBG #ifndef MALLOCDBG
void freelist(void *p1); void freelist(void *p1);
void removelist(void *l, void *p); void removelist(void *l, void *p);
@ -49,7 +48,6 @@ void removelist(void *l, void *p);
#endif #endif
unsigned int listlen(void *l); unsigned int listlen(void *l);
void invert_list(void * heap);
#define addlist2(l, p) (*l = p, l = &p->next) #define addlist2(l, p) (*l = p, l = &p->next)
void *listelem(void *l, int n); void *listelem(void *l, int n);

View File

@ -118,11 +118,21 @@ building_getregion(const building& b)
} }
static void static void
building_setregion(building& b, region& r) building_setregion(building& bld, region& r)
{ {
choplist(&b.region->buildings, &b); building * b = &bld;
addlist(&r.buildings, &b); building ** blist = &b->region->buildings;
b.region = &r; while (*blist && *blist!=b) {
blist = &(*blist)->next;
}
*blist = b->next;
b->next = NULL;
blist = &r.buildings;
while (*blist && *blist!=b) blist = &(*blist)->next;
*blist = b;
b->region = &r;
} }
static std::ostream& static std::ostream&