ship and building owners encapsulated in accessors

tests added
This commit is contained in:
Enno Rehling 2012-05-17 15:23:15 -07:00
parent 7789e0534e
commit ff33af3c65
17 changed files with 425 additions and 114 deletions

View file

@ -614,20 +614,20 @@ static int tolua_unit_get_building(lua_State * L)
return 1; 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) static int tolua_unit_set_building(lua_State * L)
{ {
unit *self = (unit *) tolua_tousertype(L, 1, 0); unit *u = (unit *) tolua_tousertype(L, 1, 0);
if (self->faction) { if (u->faction) {
unit_setbuilding(self, (building *) tolua_tousertype(L, 2, 0)); 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; return 0;
} }

View file

@ -639,10 +639,8 @@ static void give_control(unit * u, unit * u2)
} }
} }
if (u->ship) { 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) int give_control_cmd(unit * u, order * ord)

View file

@ -53,7 +53,7 @@ static void test_rename_building(CuTest * tc)
b = new_building(btype, r, default_locale); b = new_building(btype, r, default_locale);
f = test_create_faction(rc_find("human")); f = test_create_faction(rc_find("human"));
u = test_create_unit(f, r); u = test_create_unit(f, r);
u->building = b; u_set_building(u, b);
fset(u, UFL_OWNER); fset(u, UFL_OWNER);
rename_building(u, NULL, b, "Villa Nagel"); 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); b = new_building(btype, r, default_locale);
f = test_create_faction(rc_find("human")); f = test_create_faction(rc_find("human"));
u = test_create_unit(f, r); 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"); rename_building(u, NULL, b, "Villa Nagel");
CuAssertStrEquals(tc, "Villa Nagel", b->name); CuAssertStrEquals(tc, "Villa Nagel", b->name);

View file

@ -61,8 +61,7 @@ static void market_curse(CuTest * tc)
f = addfaction("nobody@eressea.de", NULL, rc, default_locale, 0); f = addfaction("nobody@eressea.de", NULL, rc, default_locale, 0);
u = create_unit(r, f, 1, f->race, 0, 0, 0); u = create_unit(r, f, 1, f->race, 0, 0, 0);
u->building = b; u_set_building(u, b);
u->flags |= UFL_OWNER;
do_markets(); do_markets();

View file

@ -911,8 +911,9 @@ static void move_iceberg(region * r)
while (rc->units) { while (rc->units) {
building *b = rc->units->building; building *b = rc->units->building;
u = rc->units; u = rc->units;
u->building = 0; /* prevent leaving in move_unit */
move_unit(rc->units, r, NULL); 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 */ /* Beschädigte Schiffe können sinken */

View file

@ -94,6 +94,7 @@
<ClCompile Include="kernel\binarystore.c" /> <ClCompile Include="kernel\binarystore.c" />
<ClCompile Include="kernel\build.c" /> <ClCompile Include="kernel\build.c" />
<ClCompile Include="kernel\building.c" /> <ClCompile Include="kernel\building.c" />
<ClCompile Include="kernel\building_test.c" />
<ClCompile Include="kernel\calendar.c" /> <ClCompile Include="kernel\calendar.c" />
<ClCompile Include="kernel\command.c" /> <ClCompile Include="kernel\command.c" />
<ClCompile Include="kernel\config.c" /> <ClCompile Include="kernel\config.c" />

View file

@ -304,6 +304,9 @@
<ClCompile Include="kernel\reports_test.c"> <ClCompile Include="kernel\reports_test.c">
<Filter>kernel</Filter> <Filter>kernel</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="kernel\building_test.c">
<Filter>kernel</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="kernel\alchemy.h"> <ClInclude Include="kernel\alchemy.h">

View file

@ -77,7 +77,7 @@ static void test_defenders_get_building_bonus(CuTest * tc)
du = test_create_unit(test_create_faction(rc_find("human")), r); du = test_create_unit(test_create_faction(rc_find("human")), r);
au = 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); b = make_battle(r);
ds = make_side(b, du->faction, 0, 0, 0); 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; bld->size = 10;
au = test_create_unit(test_create_faction(rc_find("human")), r); au = test_create_unit(test_create_faction(rc_find("human")), r);
au->building = bld; u_set_building(au, bld);
b = make_battle(r); b = make_battle(r);
as = make_side(b, au->faction, 0, 0, 0); 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")); f = test_create_faction(rc_find("human"));
au = test_create_unit(f, r); au = test_create_unit(f, r);
scale_number(au, 9); scale_number(au, 9);
au->building = bld; u_set_building(au, bld);
du = test_create_unit(f, r); du = test_create_unit(f, r);
du->building = bld; u_set_building(du, bld);
scale_number(du, 2); scale_number(du, 2);
b = make_battle(r); b = make_battle(r);

View file

@ -360,14 +360,13 @@ int destroy_cmd(unit * u, struct order *ord)
return 0; return 0;
} }
if (!fval(u, UFL_OWNER)) {
cmistake(u, ord, 138, MSG_PRODUCE);
return 0;
}
if (u->building) { if (u->building) {
building *b = 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)) { if (fval(b->type, BTF_INDESTRUCTIBLE)) {
cmistake(u, ord, 138, MSG_PRODUCE); cmistake(u, ord, 138, MSG_PRODUCE);
return 0; return 0;
@ -377,8 +376,8 @@ int destroy_cmd(unit * u, struct order *ord)
/* all units leave the building */ /* all units leave the building */
for (u2 = r->units; u2; u2 = u2->next) { for (u2 = r->units; u2; u2 = u2->next) {
if (u2->building == b) { if (u2->building == b) {
u2->building = 0;
freset(u2, UFL_OWNER); freset(u2, UFL_OWNER);
leave_building(u2);
} }
} }
ADDMSG(&u->faction->msgs, msg_message("destroy", "building unit", b, u)); 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) { } else if (u->ship) {
sh = u->ship; sh = u->ship;
if (u!=ship_owner(sh)) {
cmistake(u, ord, 138, MSG_PRODUCE);
return 0;
}
if (fval(r->terrain, SEA_REGION)) { if (fval(r->terrain, SEA_REGION)) {
cmistake(u, ord, 14, MSG_EVENT); cmistake(u, ord, 14, MSG_EVENT);
return 0; 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. */ /* Die Einheit befindet sich automatisch im Inneren der neuen Burg. */
if (leave(u, false)) { if (leave(u, false)) {
u->building = b; u_set_building(u, b);
fset(u, UFL_OWNER); assert(building_owner(b)==u);
} }
#ifdef WDW_PYRAMID #ifdef WDW_PYRAMID
if (b->type == bt_find("pyramid") && f_get_alliance(u->faction) != NULL) { 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 (leave(u, false)) {
if (building_owner(b) == 0) {
fset(u, UFL_OWNER);
}
fset(u, UFL_ENTER); fset(u, UFL_ENTER);
u->building = b; u_set_building(u, b);
return true; return true;
} }
return false; return false;

View file

@ -145,8 +145,9 @@ building_type *bt_find(const char *name)
void bt_register(building_type * type) void bt_register(building_type * type)
{ {
if (type->init) if (type->init) {
type->init(type); type->init(type);
}
ql_push(&buildingtypes, (void *)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) void building_set_owner(struct building *b, struct unit * owner)
{ {
unit * u;
assert(b && owner && owner->building==b); assert(b && owner && owner->building==b);
if (b->_owner && b->_owner!=owner) {
for (u = b->region->units; u; u = u->next) { freset(b->_owner, UFL_OWNER);
if (u->building == b) {
freset(owner, UFL_OWNER);
}
} }
b->_owner = owner;
fset(owner, UFL_OWNER); fset(owner, UFL_OWNER);
} }
unit *building_owner(const building * b) unit *building_owner(const building * bld)
{ {
unit *u = NULL; unit *owner = bld->_owner;
unit *first = NULL; if (owner && (owner->building!=bld || owner->number<=0)) {
region *r = b->region; unit *u, *heir = 0;
/* Prüfen ob Eigentümer am leben. */
for (u = r->units; u; u = u->next) { /* Eigentümer tot oder kein Eigentümer vorhanden. Erste lebende Einheit
if (u->building == b) { * nehmen. */
if (!first && u->number > 0) for (u = bld->region->units; u; u = u->next) {
first = u; if (u->building == bld) {
if (fval(u, UFL_OWNER) && u->number > 0) if (u->number > 0) {
return u; if (u->faction==owner->faction) {
if (u->number == 0) heir = u;
break;
}
else if (!heir) {
heir = u; /* you'll do in an emergency */
}
}
freset(u, UFL_OWNER); freset(u, UFL_OWNER);
}
}
freset(owner, UFL_OWNER);
owner->building = 0;
owner = heir;
if (owner) {
fset(owner, UFL_OWNER);
} }
} }
return owner;
/* Eigentümer tot oder kein Eigentümer vorhanden. Erste lebende Einheit
* nehmen. */
if (first) {
fset(first, UFL_OWNER);
}
return first;
} }
const char *building_getname(const building * self) const char *building_getname(const building * self)

View file

@ -104,6 +104,7 @@ extern "C" {
const struct building_type *type; const struct building_type *type;
struct region *region; struct region *region;
struct unit *_owner; /* you should always use building_owner(), never this naked pointer */
char *name; char *name;
char *display; char *display;
struct attrib *attribs; struct attrib *attribs;

324
src/kernel/building_test.c Normal file
View file

@ -0,0 +1,324 @@
#include <platform.h>
#include <kernel/config.h>
#include <kernel/types.h>
#include <kernel/race.h>
#include <kernel/region.h>
#include <kernel/building.h>
#include <kernel/unit.h>
#include <cutest/CuTest.h>
#include <tests.h>
#include <stdlib.h>
#include <string.h>
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;
}

View file

@ -278,39 +278,39 @@ void getshipweight(const ship * sh, int *sweight, int *scabins)
void ship_set_owner(ship * sh, unit * u) { void ship_set_owner(ship * sh, unit * u) {
assert(u->ship==sh); assert(u->ship==sh);
if (sh->owner && sh->owner!=u) { if (sh->_owner && sh->_owner!=u) {
freset(sh->owner, UFL_OWNER); freset(sh->_owner, UFL_OWNER);
} }
sh->owner = u; sh->_owner = u;
fset(u, UFL_OWNER); fset(u, UFL_OWNER);
} }
unit *ship_owner(ship * sh) unit *ship_owner(const ship * sh)
{ {
unit *owner = sh->owner; unit *owner = sh->_owner;
if (owner && owner->number<=0) { if (owner && (owner->ship!=sh || owner->number<=0)) {
unit *u, *first = NULL; unit *u, *heir = 0;
owner->ship = 0; owner->ship = 0;
freset(owner, UFL_OWNER);
/* Prüfen ob Eigentümer am leben. */ /* Prüfen ob Eigentümer am leben. */
for (u = sh->region->units; u; u = u->next) { for (u = sh->region->units; u; u = u->next) {
if (u->ship == sh) { if (u->ship == sh) {
if (u->number > 0) { if (u->number > 0) {
if (u->faction==owner->faction) { if (u->faction==owner->faction) {
first = u; heir = u;
break; break;
} }
else if (!first) { else if (!heir) {
first = u; /* you'll do in an emergency */ heir = u; /* you'll do in an emergency */
} }
} }
freset(u, UFL_OWNER);
} }
} }
owner = first; freset(owner, UFL_OWNER);
owner = heir;
if (owner) { if (owner) {
fset(owner, UFL_OWNER); fset(owner, UFL_OWNER);
sh->owner = owner;
} }
} }
/* Eigentümer tot oder kein Eigentümer vorhanden. Erste lebende Einheit /* Eigentümer tot oder kein Eigentümer vorhanden. Erste lebende Einheit

View file

@ -81,7 +81,7 @@ extern "C" {
typedef struct ship { typedef struct ship {
struct ship *next; struct ship *next;
struct ship *nexthash; struct ship *nexthash;
struct unit * owner; struct unit * _owner; /* never use directly, always use ship_owner() */
int no; int no;
struct region *region; struct region *region;
char *name; char *name;
@ -96,7 +96,7 @@ extern "C" {
extern void damage_ship(struct ship * sh, double percent); extern void damage_ship(struct ship * sh, double percent);
extern void ship_set_owner(struct ship * sh, struct unit * u); 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 const char *shipname(const struct ship *self);
extern int shipcapacity(const struct ship *sh); extern int shipcapacity(const struct ship *sh);
extern void getshipweight(const struct ship *sh, int *weight, int *cabins); extern void getshipweight(const struct ship *sh, int *weight, int *cabins);

View file

@ -1,5 +1,6 @@
#include <platform.h> #include <platform.h>
#include <kernel/config.h>
#include <kernel/types.h> #include <kernel/types.h>
#include <kernel/race.h> #include <kernel/race.h>
#include <kernel/region.h> #include <kernel/region.h>
@ -43,8 +44,10 @@ static void test_ship_set_owner(CuTest * tc)
sh = test_create_ship(r, stype); sh = test_create_ship(r, stype);
u1 = test_create_unit(f, r); u1 = test_create_unit(f, r);
u2 = test_create_unit(f, r);
u_set_ship(u1, sh); u_set_ship(u1, sh);
CuAssertPtrEquals(tc, u1, ship_owner(sh));
u2 = test_create_unit(f, r);
u_set_ship(u2, sh); u_set_ship(u2, sh);
CuAssertPtrEquals(tc, u1, ship_owner(sh)); CuAssertPtrEquals(tc, u1, ship_owner(sh));
ship_set_owner(sh, u2); ship_set_owner(sh, u2);

View file

@ -778,17 +778,17 @@ void u_set_building(unit * u, building * b)
{ {
assert(b && !u->building); /* you must leave first */ assert(b && !u->building); /* you must leave first */
u->building = b; u->building = b;
if (b && !b->_owner) {
building_set_owner(b, u);
}
} }
void u_set_ship(unit * u, ship * sh) void u_set_ship(unit * u, ship * sh)
{ {
assert(!u->ship); /* you must leave_ship */ assert(!u->ship); /* you must leave_ship */
if (sh) { u->ship = sh;
u->ship = sh; if (sh && !sh->_owner) {
if (!sh->owner) { ship_set_owner(sh, u);
sh->owner = u;
fset(u, UFL_OWNER);
}
} }
} }
@ -798,37 +798,14 @@ void leave_ship(unit * u)
if (!sh) return; if (!sh) return;
u->ship = 0; u->ship = 0;
set_leftship(u, sh); 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) void leave_building(unit * u)
{ {
struct building *b = u->building; 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; unit *u2, *owner = NULL;
freset(u, UFL_OWNER); 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 */ /* erbt Gebäude/Schiff */
if (creator->region == r) { 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)) { if (creator->ship && fval(u->race, RCF_CANSAIL)) {
u_set_ship(u, creator->ship); u_set_ship(u, creator->ship);
} }

View file

@ -10,6 +10,7 @@
#include <util/umlaut_test.c> #include <util/umlaut_test.c>
#include <kernel/move_test.c> #include <kernel/move_test.c>
#include <kernel/ship_test.c> #include <kernel/ship_test.c>
#include <kernel/building_test.c>
#include <kernel/spell_test.c> #include <kernel/spell_test.c>
#include <kernel/curse_test.c> #include <kernel/curse_test.c>
#include <kernel/battle_test.c> #include <kernel/battle_test.c>
@ -47,6 +48,7 @@ int RunAllTests(void)
CuSuiteAddSuite(suite, get_move_suite()); CuSuiteAddSuite(suite, get_move_suite());
CuSuiteAddSuite(suite, get_reports_suite()); CuSuiteAddSuite(suite, get_reports_suite());
CuSuiteAddSuite(suite, get_ship_suite()); CuSuiteAddSuite(suite, get_ship_suite());
CuSuiteAddSuite(suite, get_building_suite());
CuSuiteAddSuite(suite, get_spell_suite()); CuSuiteAddSuite(suite, get_spell_suite());
CuSuiteAddSuite(suite, get_laws_suite()); CuSuiteAddSuite(suite, get_laws_suite());
CuSuiteAddSuite(suite, get_battle_suite()); CuSuiteAddSuite(suite, get_battle_suite());