diff --git a/src/bindings/bind_unit.c b/src/bindings/bind_unit.c
index 139740237..3b0198d2c 100644
--- a/src/bindings/bind_unit.c
+++ b/src/bindings/bind_unit.c
@@ -614,20 +614,20 @@ static int tolua_unit_get_building(lua_State * L)
return 1;
}
-static void unit_setbuilding(unit * u, building * b)
-{
- leave(u, true);
- if (b && u->region != b->region) {
- move_unit(u, b->region, NULL);
- }
- u->building = b;
-}
-
static int tolua_unit_set_building(lua_State * L)
{
- unit *self = (unit *) tolua_tousertype(L, 1, 0);
- if (self->faction) {
- unit_setbuilding(self, (building *) tolua_tousertype(L, 2, 0));
+ unit *u = (unit *) tolua_tousertype(L, 1, 0);
+ if (u->faction) {
+ building * b = (building *) tolua_tousertype(L, 2, 0);
+ if (b!=u->building) {
+ leave(u, true);
+ if (b) {
+ if (u->region != b->region) {
+ move_unit(u, b->region, NULL);
+ }
+ u_set_building(u, b);
+ }
+ }
}
return 0;
}
diff --git a/src/gamecode/economy.c b/src/gamecode/economy.c
index 32c7e1182..6b99573a8 100644
--- a/src/gamecode/economy.c
+++ b/src/gamecode/economy.c
@@ -639,10 +639,8 @@ static void give_control(unit * u, unit * u2)
}
}
if (u->ship) {
- u->ship->owner = u2;
+ ship_set_owner(u->ship, u2);
}
- freset(u, UFL_OWNER);
- fset(u2, UFL_OWNER);
}
int give_control_cmd(unit * u, order * ord)
diff --git a/src/gamecode/laws_test.c b/src/gamecode/laws_test.c
index 02af945dc..e8fbd1895 100644
--- a/src/gamecode/laws_test.c
+++ b/src/gamecode/laws_test.c
@@ -53,7 +53,7 @@ static void test_rename_building(CuTest * tc)
b = new_building(btype, r, default_locale);
f = test_create_faction(rc_find("human"));
u = test_create_unit(f, r);
- u->building = b;
+ u_set_building(u, b);
fset(u, UFL_OWNER);
rename_building(u, NULL, b, "Villa Nagel");
@@ -77,8 +77,7 @@ static void test_rename_building_twice(CuTest * tc)
b = new_building(btype, r, default_locale);
f = test_create_faction(rc_find("human"));
u = test_create_unit(f, r);
- u->building = b;
- fset(u, UFL_OWNER);
+ u_set_building(u, b);
rename_building(u, NULL, b, "Villa Nagel");
CuAssertStrEquals(tc, "Villa Nagel", b->name);
diff --git a/src/gamecode/market_test.c b/src/gamecode/market_test.c
index d60c71982..c60876995 100644
--- a/src/gamecode/market_test.c
+++ b/src/gamecode/market_test.c
@@ -61,8 +61,7 @@ static void market_curse(CuTest * tc)
f = addfaction("nobody@eressea.de", NULL, rc, default_locale, 0);
u = create_unit(r, f, 1, f->race, 0, 0, 0);
- u->building = b;
- u->flags |= UFL_OWNER;
+ u_set_building(u, b);
do_markets();
diff --git a/src/gamecode/randenc.c b/src/gamecode/randenc.c
index a84f792b5..b0f422f0b 100644
--- a/src/gamecode/randenc.c
+++ b/src/gamecode/randenc.c
@@ -911,8 +911,9 @@ static void move_iceberg(region * r)
while (rc->units) {
building *b = rc->units->building;
u = rc->units;
+ u->building = 0; /* prevent leaving in move_unit */
move_unit(rc->units, r, NULL);
- u->building = b; /* move_unit macht ein leave() */
+ u_set_building(u, b); /* undo leave-prevention */
}
/* Beschädigte Schiffe können sinken */
diff --git a/src/kernel.vcxproj b/src/kernel.vcxproj
index c998520ac..240cc1a6d 100644
--- a/src/kernel.vcxproj
+++ b/src/kernel.vcxproj
@@ -94,6 +94,7 @@
+
diff --git a/src/kernel.vcxproj.filters b/src/kernel.vcxproj.filters
index 0239a0193..8c6cdcdf1 100644
--- a/src/kernel.vcxproj.filters
+++ b/src/kernel.vcxproj.filters
@@ -304,6 +304,9 @@
kernel
+
+ kernel
+
diff --git a/src/kernel/battle_test.c b/src/kernel/battle_test.c
index ceac668c7..c86a7f0b8 100644
--- a/src/kernel/battle_test.c
+++ b/src/kernel/battle_test.c
@@ -77,7 +77,7 @@ static void test_defenders_get_building_bonus(CuTest * tc)
du = test_create_unit(test_create_faction(rc_find("human")), r);
au = test_create_unit(test_create_faction(rc_find("human")), r);
- du->building = bld;
+ u_set_building(du, bld);
b = make_battle(r);
ds = make_side(b, du->faction, 0, 0, 0);
@@ -119,8 +119,7 @@ static void test_attackers_get_no_building_bonus(CuTest * tc)
bld->size = 10;
au = test_create_unit(test_create_faction(rc_find("human")), r);
- au->building = bld;
-
+ u_set_building(au, bld);
b = make_battle(r);
as = make_side(b, au->faction, 0, 0, 0);
@@ -151,9 +150,9 @@ static void test_building_bonus_respects_size(CuTest * tc)
f = test_create_faction(rc_find("human"));
au = test_create_unit(f, r);
scale_number(au, 9);
- au->building = bld;
+ u_set_building(au, bld);
du = test_create_unit(f, r);
- du->building = bld;
+ u_set_building(du, bld);
scale_number(du, 2);
b = make_battle(r);
diff --git a/src/kernel/build.c b/src/kernel/build.c
index a3ab10b8c..fcda6483f 100644
--- a/src/kernel/build.c
+++ b/src/kernel/build.c
@@ -360,14 +360,13 @@ int destroy_cmd(unit * u, struct order *ord)
return 0;
}
- if (!fval(u, UFL_OWNER)) {
- cmistake(u, ord, 138, MSG_PRODUCE);
- return 0;
- }
-
if (u->building) {
building *b = u->building;
+ if (u!=building_owner(b)) {
+ cmistake(u, ord, 138, MSG_PRODUCE);
+ return 0;
+ }
if (fval(b->type, BTF_INDESTRUCTIBLE)) {
cmistake(u, ord, 138, MSG_PRODUCE);
return 0;
@@ -377,8 +376,8 @@ int destroy_cmd(unit * u, struct order *ord)
/* all units leave the building */
for (u2 = r->units; u2; u2 = u2->next) {
if (u2->building == b) {
- u2->building = 0;
freset(u2, UFL_OWNER);
+ leave_building(u2);
}
}
ADDMSG(&u->faction->msgs, msg_message("destroy", "building unit", b, u));
@@ -393,6 +392,10 @@ int destroy_cmd(unit * u, struct order *ord)
} else if (u->ship) {
sh = u->ship;
+ if (u!=ship_owner(sh)) {
+ cmistake(u, ord, 138, MSG_PRODUCE);
+ return 0;
+ }
if (fval(r->terrain, SEA_REGION)) {
cmistake(u, ord, 14, MSG_EVENT);
return 0;
@@ -970,8 +973,8 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
/* Die Einheit befindet sich automatisch im Inneren der neuen Burg. */
if (leave(u, false)) {
- u->building = b;
- fset(u, UFL_OWNER);
+ u_set_building(u, b);
+ assert(building_owner(b)==u);
}
#ifdef WDW_PYRAMID
if (b->type == bt_find("pyramid") && f_get_alliance(u->faction) != NULL) {
@@ -1297,11 +1300,8 @@ static boolean enter_building(unit * u, order * ord, int id, boolean report)
}
if (leave(u, false)) {
- if (building_owner(b) == 0) {
- fset(u, UFL_OWNER);
- }
fset(u, UFL_ENTER);
- u->building = b;
+ u_set_building(u, b);
return true;
}
return false;
diff --git a/src/kernel/building.c b/src/kernel/building.c
index f36636047..1295d47b1 100644
--- a/src/kernel/building.c
+++ b/src/kernel/building.c
@@ -145,8 +145,9 @@ building_type *bt_find(const char *name)
void bt_register(building_type * type)
{
- if (type->init)
+ if (type->init) {
type->init(type);
+ }
ql_push(&buildingtypes, (void *)type);
}
@@ -616,43 +617,44 @@ const char *buildingname(const building * b)
void building_set_owner(struct building *b, struct unit * owner)
{
- unit * u;
-
assert(b && owner && owner->building==b);
-
- for (u = b->region->units; u; u = u->next) {
- if (u->building == b) {
- freset(owner, UFL_OWNER);
- }
+ if (b->_owner && b->_owner!=owner) {
+ freset(b->_owner, UFL_OWNER);
}
+ b->_owner = owner;
fset(owner, UFL_OWNER);
}
-unit *building_owner(const building * b)
+unit *building_owner(const building * bld)
{
- unit *u = NULL;
- unit *first = NULL;
- region *r = b->region;
- /* Prüfen ob Eigentümer am leben. */
+ unit *owner = bld->_owner;
+ if (owner && (owner->building!=bld || owner->number<=0)) {
+ unit *u, *heir = 0;
- for (u = r->units; u; u = u->next) {
- if (u->building == b) {
- if (!first && u->number > 0)
- first = u;
- if (fval(u, UFL_OWNER) && u->number > 0)
- return u;
- if (u->number == 0)
+ /* Eigentümer tot oder kein Eigentümer vorhanden. Erste lebende Einheit
+ * nehmen. */
+ for (u = bld->region->units; u; u = u->next) {
+ if (u->building == bld) {
+ if (u->number > 0) {
+ if (u->faction==owner->faction) {
+ heir = u;
+ break;
+ }
+ else if (!heir) {
+ heir = u; /* you'll do in an emergency */
+ }
+ }
freset(u, UFL_OWNER);
+ }
+ }
+ freset(owner, UFL_OWNER);
+ owner->building = 0;
+ owner = heir;
+ if (owner) {
+ fset(owner, UFL_OWNER);
}
}
-
- /* Eigentümer tot oder kein Eigentümer vorhanden. Erste lebende Einheit
- * nehmen. */
-
- if (first) {
- fset(first, UFL_OWNER);
- }
- return first;
+ return owner;
}
const char *building_getname(const building * self)
diff --git a/src/kernel/building.h b/src/kernel/building.h
index 7fdbfaf1e..bacf91d93 100644
--- a/src/kernel/building.h
+++ b/src/kernel/building.h
@@ -104,6 +104,7 @@ extern "C" {
const struct building_type *type;
struct region *region;
+ struct unit *_owner; /* you should always use building_owner(), never this naked pointer */
char *name;
char *display;
struct attrib *attribs;
diff --git a/src/kernel/building_test.c b/src/kernel/building_test.c
new file mode 100644
index 000000000..0e09aa1c8
--- /dev/null
+++ b/src/kernel/building_test.c
@@ -0,0 +1,324 @@
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+static void test_register_building(CuTest * tc)
+{
+ building_type *btype;
+
+ test_cleanup();
+
+ btype = (building_type *)calloc(sizeof(building_type), 1);
+ btype->_name = strdup("herp");
+ bt_register(btype);
+
+ CuAssertPtrNotNull(tc, bt_find("herp"));
+}
+
+static void test_building_set_owner(CuTest * tc)
+{
+ struct region *r;
+ struct building *bld;
+ struct unit *u1, *u2;
+ struct faction *f;
+ const struct building_type *btype;
+ const struct race *human;
+
+ test_cleanup();
+ test_create_world();
+
+ human = rc_find("human");
+ btype = bt_find("castle");
+ f = test_create_faction(human);
+ r = findregion(0, 0);
+
+ bld = test_create_building(r, btype);
+ u1 = test_create_unit(f, r);
+ u_set_building(u1, bld);
+ CuAssertPtrEquals(tc, u1, building_owner(bld));
+
+ u2 = test_create_unit(f, r);
+ u_set_building(u2, bld);
+ CuAssertPtrEquals(tc, u1, building_owner(bld));
+ building_set_owner(bld, u2);
+ CuAssertPtrEquals(tc, u2, building_owner(bld));
+}
+
+static void test_buildingowner_goes_to_next_after_death(CuTest * tc)
+{
+ struct region *r;
+ struct building *bld;
+ struct unit *u, *u2;
+ struct faction *f;
+ const struct building_type *btype;
+ const struct race *human;
+
+ test_cleanup();
+ test_create_world();
+
+ human = rc_find("human");
+ CuAssertPtrNotNull(tc, human);
+
+ btype = bt_find("castle");
+ CuAssertPtrNotNull(tc, btype);
+
+ f = test_create_faction(human);
+ r = findregion(0, 0);
+
+ bld = test_create_building(r, btype);
+ CuAssertPtrNotNull(tc, bld);
+
+ u = test_create_unit(f, r);
+ u2 = test_create_unit(f, r);
+ CuAssertPtrNotNull(tc, u);
+ u_set_building(u, bld);
+ u_set_building(u2, bld);
+ CuAssertPtrEquals(tc, u, building_owner(bld));
+ u->number = 0;
+ CuAssertPtrEquals(tc, u2, building_owner(bld));
+}
+
+static void test_buildingowner_goes_to_other_after_death(CuTest * tc)
+{
+ struct region *r;
+ struct building *bld;
+ struct unit *u, *u2;
+ struct faction *f;
+ const struct building_type *btype;
+ const struct race *human;
+
+ test_cleanup();
+ test_create_world();
+
+ human = rc_find("human");
+ CuAssertPtrNotNull(tc, human);
+
+ btype = bt_find("castle");
+ CuAssertPtrNotNull(tc, btype);
+
+ f = test_create_faction(human);
+ r = findregion(0, 0);
+
+ bld = test_create_building(r, btype);
+ CuAssertPtrNotNull(tc, bld);
+
+ u2 = test_create_unit(f, r);
+ u = test_create_unit(f, r);
+ CuAssertPtrNotNull(tc, u);
+ u_set_building(u, bld);
+ CuAssertPtrEquals(tc, u, building_owner(bld));
+ u_set_building(u2, bld);
+ CuAssertPtrEquals(tc, u, building_owner(bld));
+ u->number = 0;
+ CuAssertPtrEquals(tc, u2, building_owner(bld));
+}
+
+static void test_buildingowner_goes_to_same_faction_after_death(CuTest * tc)
+{
+ struct region *r;
+ struct building *bld;
+ struct unit *u, *u2, *u3;
+ struct faction *f1, *f2;
+ const struct building_type *btype;
+ const struct race *human;
+
+ test_cleanup();
+ test_create_world();
+
+ human = rc_find("human");
+ CuAssertPtrNotNull(tc, human);
+
+ btype = bt_find("castle");
+ CuAssertPtrNotNull(tc, btype);
+
+ f1 = test_create_faction(human);
+ f2 = test_create_faction(human);
+ r = findregion(0, 0);
+
+ bld = test_create_building(r, btype);
+ CuAssertPtrNotNull(tc, bld);
+
+ u2 = test_create_unit(f2, r);
+ u3 = test_create_unit(f1, r);
+ u = test_create_unit(f1, r);
+ CuAssertPtrNotNull(tc, u);
+ u_set_building(u, bld);
+ u_set_building(u2, bld);
+ u_set_building(u3, bld);
+ CuAssertPtrEquals(tc, u, building_owner(bld));
+ CuAssertTrue(tc, fval(u, UFL_OWNER));
+ u->number = 0;
+ CuAssertPtrEquals(tc, u3, building_owner(bld));
+ CuAssertTrue(tc, !fval(u, UFL_OWNER));
+ CuAssertTrue(tc, fval(u3, UFL_OWNER));
+ u3->number = 0;
+ CuAssertPtrEquals(tc, u2, building_owner(bld));
+ CuAssertTrue(tc, !fval(u3, UFL_OWNER));
+ CuAssertTrue(tc, fval(u2, UFL_OWNER));
+}
+
+static void test_buildingowner_goes_to_next_after_leave(CuTest * tc)
+{
+ struct region *r;
+ struct building *bld;
+ struct unit *u, *u2;
+ struct faction *f;
+ const struct building_type *btype;
+ const struct race *human;
+
+ test_cleanup();
+ test_create_world();
+
+ human = rc_find("human");
+ CuAssertPtrNotNull(tc, human);
+
+ btype = bt_find("castle");
+ CuAssertPtrNotNull(tc, btype);
+
+ f = test_create_faction(human);
+ r = findregion(0, 0);
+
+ bld = test_create_building(r, btype);
+ CuAssertPtrNotNull(tc, bld);
+
+ u = test_create_unit(f, r);
+ u2 = test_create_unit(f, r);
+ CuAssertPtrNotNull(tc, u);
+ u_set_building(u, bld);
+ u_set_building(u2, bld);
+ CuAssertPtrEquals(tc, u, building_owner(bld));
+ leave_building(u);
+ CuAssertPtrEquals(tc, u2, building_owner(bld));
+}
+
+static void test_buildingowner_goes_to_other_after_leave(CuTest * tc)
+{
+ struct region *r;
+ struct building *bld;
+ struct unit *u, *u2;
+ struct faction *f;
+ const struct building_type *btype;
+ const struct race *human;
+
+ test_cleanup();
+ test_create_world();
+
+ human = rc_find("human");
+ CuAssertPtrNotNull(tc, human);
+
+ btype = bt_find("castle");
+ CuAssertPtrNotNull(tc, btype);
+
+ f = test_create_faction(human);
+ r = findregion(0, 0);
+
+ bld = test_create_building(r, btype);
+ CuAssertPtrNotNull(tc, bld);
+
+ u2 = test_create_unit(f, r);
+ u = test_create_unit(f, r);
+ CuAssertPtrNotNull(tc, u);
+ u_set_building(u, bld);
+ u_set_building(u2, bld);
+ CuAssertPtrEquals(tc, u, building_owner(bld));
+ leave_building(u);
+ CuAssertPtrEquals(tc, u2, building_owner(bld));
+}
+
+static void test_buildingowner_goes_to_same_faction_after_leave(CuTest * tc)
+{
+ struct region *r;
+ struct building *bld;
+ struct unit *u, *u2, *u3;
+ struct faction *f1, *f2;
+ const struct building_type *btype;
+ const struct race *human;
+
+ test_cleanup();
+ test_create_world();
+
+ human = rc_find("human");
+ CuAssertPtrNotNull(tc, human);
+
+ btype = bt_find("castle");
+ CuAssertPtrNotNull(tc, btype);
+
+ f1 = test_create_faction(human);
+ f2 = test_create_faction(human);
+ r = findregion(0, 0);
+
+ bld = test_create_building(r, btype);
+ CuAssertPtrNotNull(tc, bld);
+
+ u2 = test_create_unit(f2, r);
+ u3 = test_create_unit(f1, r);
+ u = test_create_unit(f1, r);
+ CuAssertPtrNotNull(tc, u);
+ u_set_building(u, bld);
+ u_set_building(u2, bld);
+ u_set_building(u3, bld);
+ CuAssertPtrEquals(tc, u, building_owner(bld));
+ leave_building(u);
+ CuAssertPtrEquals(tc, u3, building_owner(bld));
+ leave_building(u3);
+ CuAssertPtrEquals(tc, u2, building_owner(bld));
+ leave_building(u2);
+ CuAssertPtrEquals(tc, 0, building_owner(bld));
+}
+
+static void test_buildingowner_resets_when_dead(CuTest * tc)
+{
+ struct region *r;
+ struct building *bld;
+ struct unit *u;
+ struct faction *f;
+ const struct building_type *btype;
+ const struct race *human;
+
+ test_cleanup();
+ test_create_world();
+
+ human = rc_find("human");
+ CuAssertPtrNotNull(tc, human);
+
+ btype = bt_find("castle");
+ CuAssertPtrNotNull(tc, btype);
+
+ f = test_create_faction(human);
+ r = findregion(0, 0);
+
+ bld = test_create_building(r, btype);
+ CuAssertPtrNotNull(tc, bld);
+
+ u = test_create_unit(f, r);
+ CuAssertPtrNotNull(tc, u);
+ u_set_building(u, bld);
+ CuAssertPtrEquals(tc, u, building_owner(bld));
+ u->number = 0;
+ CuAssertPtrEquals(tc, 0, building_owner(bld));
+}
+
+CuSuite *get_building_suite(void)
+{
+ CuSuite *suite = CuSuiteNew();
+ SUITE_ADD_TEST(suite, test_register_building);
+ SUITE_ADD_TEST(suite, test_building_set_owner);
+ SUITE_ADD_TEST(suite, test_buildingowner_resets_when_dead);
+ SUITE_ADD_TEST(suite, test_buildingowner_goes_to_next_after_death);
+ SUITE_ADD_TEST(suite, test_buildingowner_goes_to_other_after_death);
+ SUITE_ADD_TEST(suite, test_buildingowner_goes_to_same_faction_after_death);
+ SUITE_ADD_TEST(suite, test_buildingowner_goes_to_next_after_leave);
+ SUITE_ADD_TEST(suite, test_buildingowner_goes_to_other_after_leave);
+ SUITE_ADD_TEST(suite, test_buildingowner_goes_to_same_faction_after_leave);
+ return suite;
+}
diff --git a/src/kernel/ship.c b/src/kernel/ship.c
index 966074a27..2d15bb52c 100644
--- a/src/kernel/ship.c
+++ b/src/kernel/ship.c
@@ -278,39 +278,39 @@ void getshipweight(const ship * sh, int *sweight, int *scabins)
void ship_set_owner(ship * sh, unit * u) {
assert(u->ship==sh);
- if (sh->owner && sh->owner!=u) {
- freset(sh->owner, UFL_OWNER);
+ if (sh->_owner && sh->_owner!=u) {
+ freset(sh->_owner, UFL_OWNER);
}
- sh->owner = u;
+ sh->_owner = u;
fset(u, UFL_OWNER);
}
-unit *ship_owner(ship * sh)
+unit *ship_owner(const ship * sh)
{
- unit *owner = sh->owner;
- if (owner && owner->number<=0) {
- unit *u, *first = NULL;
+ unit *owner = sh->_owner;
+ if (owner && (owner->ship!=sh || owner->number<=0)) {
+ unit *u, *heir = 0;
owner->ship = 0;
- freset(owner, UFL_OWNER);
/* Prüfen ob Eigentümer am leben. */
for (u = sh->region->units; u; u = u->next) {
if (u->ship == sh) {
if (u->number > 0) {
if (u->faction==owner->faction) {
- first = u;
+ heir = u;
break;
}
- else if (!first) {
- first = u; /* you'll do in an emergency */
+ else if (!heir) {
+ heir = u; /* you'll do in an emergency */
}
}
+ freset(u, UFL_OWNER);
}
}
- owner = first;
+ freset(owner, UFL_OWNER);
+ owner = heir;
if (owner) {
fset(owner, UFL_OWNER);
- sh->owner = owner;
}
}
/* Eigentümer tot oder kein Eigentümer vorhanden. Erste lebende Einheit
diff --git a/src/kernel/ship.h b/src/kernel/ship.h
index aedbff63c..b4e95a302 100644
--- a/src/kernel/ship.h
+++ b/src/kernel/ship.h
@@ -81,7 +81,7 @@ extern "C" {
typedef struct ship {
struct ship *next;
struct ship *nexthash;
- struct unit * owner;
+ struct unit * _owner; /* never use directly, always use ship_owner() */
int no;
struct region *region;
char *name;
@@ -96,7 +96,7 @@ extern "C" {
extern void damage_ship(struct ship * sh, double percent);
extern void ship_set_owner(struct ship * sh, struct unit * u);
- extern struct unit *ship_owner(struct ship *sh);
+ extern struct unit *ship_owner(const struct ship *sh);
extern const char *shipname(const struct ship *self);
extern int shipcapacity(const struct ship *sh);
extern void getshipweight(const struct ship *sh, int *weight, int *cabins);
diff --git a/src/kernel/ship_test.c b/src/kernel/ship_test.c
index 9eb6641a3..8e69a6bd4 100644
--- a/src/kernel/ship_test.c
+++ b/src/kernel/ship_test.c
@@ -1,5 +1,6 @@
#include
+#include
#include
#include
#include
@@ -43,8 +44,10 @@ static void test_ship_set_owner(CuTest * tc)
sh = test_create_ship(r, stype);
u1 = test_create_unit(f, r);
- u2 = test_create_unit(f, r);
u_set_ship(u1, sh);
+ CuAssertPtrEquals(tc, u1, ship_owner(sh));
+
+ u2 = test_create_unit(f, r);
u_set_ship(u2, sh);
CuAssertPtrEquals(tc, u1, ship_owner(sh));
ship_set_owner(sh, u2);
diff --git a/src/kernel/unit.c b/src/kernel/unit.c
index 07f80c410..3b1fdcf3b 100644
--- a/src/kernel/unit.c
+++ b/src/kernel/unit.c
@@ -778,17 +778,17 @@ void u_set_building(unit * u, building * b)
{
assert(b && !u->building); /* you must leave first */
u->building = b;
+ if (b && !b->_owner) {
+ building_set_owner(b, u);
+ }
}
void u_set_ship(unit * u, ship * sh)
{
assert(!u->ship); /* you must leave_ship */
- if (sh) {
- u->ship = sh;
- if (!sh->owner) {
- sh->owner = u;
- fset(u, UFL_OWNER);
- }
+ u->ship = sh;
+ if (sh && !sh->_owner) {
+ ship_set_owner(sh, u);
}
}
@@ -798,37 +798,14 @@ void leave_ship(unit * u)
if (!sh) return;
u->ship = 0;
set_leftship(u, sh);
-
- if (fval(u, UFL_OWNER)) {
- unit *u2, *owner = NULL;
- freset(u, UFL_OWNER);
-
- for (u2 = u->region->units; u2; u2 = u2->next) {
- if (u2->ship == sh) {
- if (u2->faction == u->faction) {
- owner = u2;
- break;
- } else if (!owner) {
- owner = u2;
- }
- }
- }
- sh->owner = owner;
- if (owner) {
- fset(owner, UFL_OWNER);
- }
- }
- assert(sh->owner!=u);
}
void leave_building(unit * u)
{
struct building *b = u->building;
- if (!b)
- return;
- u->building = NULL;
- if (fval(u, UFL_OWNER)) {
+ u->building = NULL;
+ if (b && fval(u, UFL_OWNER)) {
unit *u2, *owner = NULL;
freset(u, UFL_OWNER);
@@ -1521,7 +1498,9 @@ unit *create_unit(region * r, faction * f, int number, const struct race *urace,
/* erbt Gebäude/Schiff */
if (creator->region == r) {
- u->building = creator->building;
+ if (creator->building) {
+ u_set_building(u, creator->building);
+ }
if (creator->ship && fval(u->race, RCF_CANSAIL)) {
u_set_ship(u, creator->ship);
}
diff --git a/src/tests.c b/src/tests.c
index e55f31825..5219f9983 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -47,6 +48,7 @@ int RunAllTests(void)
CuSuiteAddSuite(suite, get_move_suite());
CuSuiteAddSuite(suite, get_reports_suite());
CuSuiteAddSuite(suite, get_ship_suite());
+ CuSuiteAddSuite(suite, get_building_suite());
CuSuiteAddSuite(suite, get_spell_suite());
CuSuiteAddSuite(suite, get_laws_suite());
CuSuiteAddSuite(suite, get_battle_suite());