forked from github/server
BUG 2462: Leuchtturm meldet keine Landregionen, beschützt Schiffe erst ab Größe 10.
This commit is contained in:
parent
820264aa82
commit
fc80e4b83e
|
@ -93,11 +93,11 @@ end
|
|||
function test_lighthouse()
|
||||
eressea.free_game()
|
||||
local r = region.create(0, 0, "mountain")
|
||||
local f = faction.create("human", "noreply@eressea.de", "de")
|
||||
local f = faction.create("human", "human@example.com")
|
||||
region.create(1, 0, "mountain")
|
||||
region.create(2, 0, "ocean")
|
||||
region.create(0, 1, "firewall")
|
||||
region.create(3, 0, "mountain")
|
||||
region.create(3, 0, "ocean")
|
||||
region.create(4, 0, "plain")
|
||||
local u = unit.create(f, r, 1)
|
||||
local b = building.create(r, "lighthouse")
|
||||
|
@ -110,7 +110,7 @@ function test_lighthouse()
|
|||
|
||||
init_reports()
|
||||
write_report(f)
|
||||
assert_true(find_in_report(f, " %(1,0%) %(vom Turm erblickt%)"))
|
||||
assert_false(find_in_report(f, " %(1,0%) %(vom Turm erblickt%)"))
|
||||
assert_true(find_in_report(f, " %(2,0%) %(vom Turm erblickt%)"))
|
||||
assert_true(find_in_report(f, " %(3,0%) %(vom Turm erblickt%)"))
|
||||
|
||||
|
|
|
@ -895,7 +895,9 @@ build_building(unit * u, const building_type * btype, int id, int want, order *
|
|||
}
|
||||
fset(b, BLD_EXPANDED);
|
||||
|
||||
update_lighthouse(b);
|
||||
if (is_lighthouse(btype)) {
|
||||
update_lighthouse(b);
|
||||
}
|
||||
|
||||
return built;
|
||||
}
|
||||
|
|
|
@ -377,7 +377,9 @@ building *new_building(const struct building_type * btype, region * r,
|
|||
bptr = &(*bptr)->next;
|
||||
*bptr = b;
|
||||
|
||||
update_lighthouse(b);
|
||||
if (is_lighthouse(b->type)) {
|
||||
update_lighthouse(b);
|
||||
}
|
||||
bname = LOC(lang, btype->_name);
|
||||
if (!bname) {
|
||||
bname = LOC(lang, parameters[P_GEBAEUDE]);
|
||||
|
@ -399,6 +401,7 @@ static building *deleted_buildings;
|
|||
void remove_building(building ** blist, building * b)
|
||||
{
|
||||
unit *u;
|
||||
region *r = b->region;
|
||||
static const struct building_type *bt_caravan, *bt_dam, *bt_tunnel;
|
||||
static int btypes;
|
||||
|
||||
|
@ -410,18 +413,19 @@ void remove_building(building ** blist, building * b)
|
|||
bt_tunnel = bt_find("tunnel");
|
||||
}
|
||||
handle_event(b->attribs, "destroy", b);
|
||||
for (u = b->region->units; u; u = u->next) {
|
||||
for (u = r->units; u; u = u->next) {
|
||||
if (u->building == b) leave(u, true);
|
||||
}
|
||||
|
||||
if (is_lighthouse(b->type)) {
|
||||
remove_lighthouse(b);
|
||||
}
|
||||
b->size = 0;
|
||||
update_lighthouse(b);
|
||||
bunhash(b);
|
||||
|
||||
/* Falls Karawanserei, Damm oder Tunnel einst<73>rzen, wird die schon
|
||||
* gebaute Strasse zur Haelfte vernichtet */
|
||||
if (b->type == bt_caravan || b->type == bt_dam || b->type == bt_tunnel) {
|
||||
region *r = b->region;
|
||||
int d;
|
||||
for (d = 0; d != MAXDIRECTIONS; ++d) {
|
||||
direction_t dir = (direction_t)d;
|
||||
|
|
114
src/lighthouse.c
114
src/lighthouse.c
|
@ -19,6 +19,11 @@ attrib_type at_lighthouse = {
|
|||
/* Rest ist NULL; tempor<6F>res, nicht alterndes Attribut */
|
||||
};
|
||||
|
||||
bool is_lighthouse(const building_type *btype)
|
||||
{
|
||||
return is_building_type(btype, "lighthouse");
|
||||
}
|
||||
|
||||
/* update_lighthouse: call this function whenever the size of a lighthouse changes
|
||||
* it adds temporary markers to the surrounding regions.
|
||||
* The existence of markers says nothing about the quality of the observer in
|
||||
|
@ -26,46 +31,57 @@ attrib_type at_lighthouse = {
|
|||
*/
|
||||
void update_lighthouse(building * lh)
|
||||
{
|
||||
if (is_building_type(lh->type, "lighthouse")) {
|
||||
region *r = lh->region;
|
||||
region *r = lh->region;
|
||||
assert(is_lighthouse(lh->type));
|
||||
|
||||
r->flags |= RF_LIGHTHOUSE;
|
||||
if (lh->size > 0) {
|
||||
int d = (int)log10(lh->size) + 1;
|
||||
int x;
|
||||
for (x = -d; x <= d; ++x) {
|
||||
int y;
|
||||
for (y = -d; y <= d; ++y) {
|
||||
attrib *a;
|
||||
region *r2;
|
||||
int px = r->x + x, py = r->y + y;
|
||||
r->flags |= RF_LIGHTHOUSE;
|
||||
if (lh->size >= 10) {
|
||||
int d = lighthouse_range(lh, NULL, NULL);
|
||||
int x;
|
||||
for (x = -d; x <= d; ++x) {
|
||||
int y;
|
||||
for (y = -d; y <= d; ++y) {
|
||||
attrib *a;
|
||||
region *r2;
|
||||
int px = r->x + x, py = r->y + y;
|
||||
|
||||
pnormalize(&px, &py, rplane(r));
|
||||
r2 = findregion(px, py);
|
||||
if (!r2 || !fval(r2->terrain, SEA_REGION))
|
||||
continue;
|
||||
if (distance(r, r2) > d)
|
||||
continue;
|
||||
a = a_find(r2->attribs, &at_lighthouse);
|
||||
while (a && a->type == &at_lighthouse) {
|
||||
building *b = (building *)a->data.v;
|
||||
if (b == lh)
|
||||
break;
|
||||
a = a->next;
|
||||
}
|
||||
if (!a) {
|
||||
a = a_add(&r2->attribs, a_new(&at_lighthouse));
|
||||
a->data.v = (void *)lh;
|
||||
}
|
||||
pnormalize(&px, &py, rplane(r));
|
||||
r2 = findregion(px, py);
|
||||
if (!r2 || !fval(r2->terrain, SEA_REGION))
|
||||
continue;
|
||||
if (distance(r, r2) > d)
|
||||
continue;
|
||||
a = a_find(r2->attribs, &at_lighthouse);
|
||||
while (a && a->type == &at_lighthouse) {
|
||||
building *b = (building *)a->data.v;
|
||||
if (b == lh)
|
||||
break;
|
||||
a = a->next;
|
||||
}
|
||||
if (!a) {
|
||||
a = a_add(&r2->attribs, a_new(&at_lighthouse));
|
||||
a->data.v = (void *)lh;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void remove_lighthouse(const building *lh) {
|
||||
building *b;
|
||||
region * r = lh->region;
|
||||
|
||||
r->flags &= ~RF_LIGHTHOUSE;
|
||||
for (b = r->buildings; b; b = b->next) {
|
||||
if (b != lh && is_lighthouse(b->type)) {
|
||||
update_lighthouse(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int lighthouse_range(const building * b, const faction * f, const unit *u)
|
||||
{
|
||||
if (fval(b, BLD_MAINTAINED) && b->size >= 10) {
|
||||
if (b->size >= 10 && (b->flags & BLD_MAINTAINED)) {
|
||||
int maxd = (int)log10(b->size) + 1;
|
||||
|
||||
if (u && skill_enabled(SK_PERCEPTION)) {
|
||||
|
@ -80,11 +96,11 @@ int lighthouse_range(const building * b, const faction * f, const unit *u)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool check_leuchtturm(region * r, faction * f)
|
||||
bool lighthouse_guarded(const region * r)
|
||||
{
|
||||
attrib *a;
|
||||
|
||||
if (!fval(r->terrain, SEA_REGION)) {
|
||||
if (!r->attribs || !(r->terrain->flags & SEA_REGION)) {
|
||||
return false;
|
||||
}
|
||||
for (a = a_find(r->attribs, &at_lighthouse); a && a->type == &at_lighthouse;
|
||||
|
@ -92,37 +108,11 @@ bool check_leuchtturm(region * r, faction * f)
|
|||
building *b = (building *)a->data.v;
|
||||
|
||||
assert(is_building_type(b->type, "lighthouse"));
|
||||
if (fval(b, BLD_MAINTAINED) && b->size >= 10) {
|
||||
if ((b->flags & BLD_MAINTAINED) && b->size >= 10) {
|
||||
int maxd = (int)log10(b->size) + 1;
|
||||
|
||||
if (skill_enabled(SK_PERCEPTION) && f) {
|
||||
region *r2 = b->region;
|
||||
unit *u;
|
||||
int c = 0;
|
||||
int d = 0;
|
||||
|
||||
for (u = r2->units; u; u = u->next) {
|
||||
if (u->building == b) {
|
||||
c += u->number;
|
||||
if (c > buildingcapacity(b))
|
||||
break;
|
||||
if (u->faction == f) {
|
||||
if (!d)
|
||||
d = distance(r, r2);
|
||||
if (maxd < d)
|
||||
break;
|
||||
if (effskill(u, SK_PERCEPTION, 0) >= d * 3)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (c)
|
||||
break; /* first unit that's no longer in the house ends the search */
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* E3A rule: no perception req'd */
|
||||
return true;
|
||||
}
|
||||
int d = distance(r, b->region);
|
||||
assert(maxd >= d);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,13 +29,16 @@ extern "C" {
|
|||
struct faction;
|
||||
struct region;
|
||||
struct building;
|
||||
struct building_type;
|
||||
struct unit;
|
||||
struct attrib;
|
||||
|
||||
extern struct attrib_type at_lighthouse;
|
||||
/* leuchtturm */
|
||||
bool check_leuchtturm(struct region *r, struct faction *f);
|
||||
bool is_lighthouse(const struct building_type *btype);
|
||||
bool lighthouse_guarded(const struct region *r);
|
||||
void update_lighthouse(struct building *b);
|
||||
void remove_lighthouse(const struct building *lh);
|
||||
int lighthouse_range(const struct building *b, const struct faction *f,
|
||||
const struct unit *u);
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ static void test_lighthouse_range(CuTest * tc)
|
|||
set_level(u1, SK_PERCEPTION, 3);
|
||||
set_level(u2, SK_PERCEPTION, 3);
|
||||
CuAssertIntEquals(tc, 0, lighthouse_range(b, NULL, NULL));
|
||||
|
||||
b->flags |= BLD_MAINTAINED;
|
||||
CuAssertIntEquals(tc, 1, lighthouse_range(b, u1->faction, u1));
|
||||
set_level(u1, SK_PERCEPTION, 6);
|
||||
|
@ -54,7 +55,7 @@ static void test_lighthouse_range(CuTest * tc)
|
|||
|
||||
static void test_lighthouse_update(CuTest * tc)
|
||||
{
|
||||
region *r1, *r2, *r3;
|
||||
region *r1, *r2, *r3, *r4;
|
||||
building *b;
|
||||
const struct terrain_type *t_ocean, *t_plain;
|
||||
|
||||
|
@ -64,20 +65,23 @@ static void test_lighthouse_update(CuTest * tc)
|
|||
r1 = test_create_region(0, 0, t_plain);
|
||||
r2 = test_create_region(1, 0, t_ocean);
|
||||
r3 = test_create_region(2, 0, t_ocean);
|
||||
r4 = test_create_region(0, 1, t_plain);
|
||||
b = test_create_building(r1, test_create_buildingtype("lighthouse"));
|
||||
b->flags |= BLD_MAINTAINED;
|
||||
CuAssertIntEquals(tc, RF_LIGHTHOUSE, r1->flags&RF_LIGHTHOUSE);
|
||||
CuAssertPtrEquals(tc, NULL, r1->attribs);
|
||||
CuAssertPtrEquals(tc, NULL, r2->attribs);
|
||||
CuAssertPtrEquals(tc, NULL, r3->attribs);
|
||||
CuAssertPtrEquals(tc, NULL, r4->attribs);
|
||||
|
||||
r1->flags = 0;
|
||||
b->size = 1;
|
||||
b->size = 9; /* minimum size for any effect is 10 */
|
||||
update_lighthouse(b);
|
||||
CuAssertIntEquals(tc, RF_LIGHTHOUSE, r1->flags&RF_LIGHTHOUSE);
|
||||
CuAssertPtrNotNull(tc, r2->attribs);
|
||||
CuAssertPtrEquals(tc, (void *)&at_lighthouse, (void *)r2->attribs->type);
|
||||
CuAssertPtrEquals(tc, NULL, r1->attribs);
|
||||
CuAssertPtrEquals(tc, NULL, r2->attribs);
|
||||
CuAssertPtrEquals(tc, NULL, r3->attribs);
|
||||
CuAssertPtrEquals(tc, NULL, r4->attribs);
|
||||
|
||||
a_removeall(&r2->attribs, NULL);
|
||||
r1->flags = 0;
|
||||
|
@ -88,6 +92,36 @@ static void test_lighthouse_update(CuTest * tc)
|
|||
CuAssertPtrEquals(tc, (void *)&at_lighthouse, (void *)r2->attribs->type);
|
||||
CuAssertPtrNotNull(tc, r3->attribs);
|
||||
CuAssertPtrEquals(tc, (void *)&at_lighthouse, (void *)r3->attribs->type);
|
||||
CuAssertPtrEquals(tc, NULL, r4->attribs);
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_lighthouse_guard(CuTest * tc) {
|
||||
region *r1, *r2, *r3, *r4;
|
||||
building *b;
|
||||
const struct terrain_type *t_ocean, *t_plain;
|
||||
|
||||
test_setup();
|
||||
t_ocean = test_create_terrain("ocean", SEA_REGION);
|
||||
t_plain = test_create_terrain("plain", LAND_REGION);
|
||||
r1 = test_create_region(0, 0, t_plain);
|
||||
r2 = test_create_region(1, 0, t_ocean);
|
||||
r3 = test_create_region(2, 0, t_ocean);
|
||||
r4 = test_create_region(0, 1, t_plain);
|
||||
b = test_create_building(r1, test_create_buildingtype("lighthouse"));
|
||||
b->flags |= BLD_MAINTAINED;
|
||||
b->size = 10;
|
||||
CuAssertIntEquals(tc, 2, lighthouse_range(b, NULL, NULL));
|
||||
update_lighthouse(b);
|
||||
CuAssertIntEquals(tc, RF_LIGHTHOUSE, r1->flags&RF_LIGHTHOUSE);
|
||||
CuAssertPtrEquals(tc, NULL, r1->attribs);
|
||||
CuAssertPtrEquals(tc, (void *)&at_lighthouse, (void *)r2->attribs->type);
|
||||
CuAssertPtrEquals(tc, (void *)&at_lighthouse, (void *)r3->attribs->type);
|
||||
CuAssertPtrEquals(tc, NULL, r4->attribs);
|
||||
CuAssertIntEquals(tc, false, lighthouse_guarded(r1));
|
||||
CuAssertIntEquals(tc, true, lighthouse_guarded(r2));
|
||||
CuAssertIntEquals(tc, true, lighthouse_guarded(r3));
|
||||
CuAssertIntEquals(tc, false, lighthouse_guarded(r4));
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
|
@ -96,5 +130,6 @@ CuSuite *get_lighthouse_suite(void)
|
|||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_lighthouse_range);
|
||||
SUITE_ADD_TEST(suite, test_lighthouse_update);
|
||||
SUITE_ADD_TEST(suite, test_lighthouse_guard);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -1779,7 +1779,7 @@ static void sail(unit * u, order * ord, region_list ** routep, bool drifting)
|
|||
|
||||
/* storms should be the first thing we do. */
|
||||
stormchance = stormyness / shipspeed(sh, u);
|
||||
if (check_leuchtturm(next_point, NULL)) {
|
||||
if (lighthouse_guarded(next_point)) {
|
||||
if (lighthouse_div > 0) {
|
||||
stormchance /= lighthouse_div;
|
||||
}
|
||||
|
@ -1867,7 +1867,7 @@ static void sail(unit * u, order * ord, region_list ** routep, bool drifting)
|
|||
if (reason == SA_NO_INSECT) {
|
||||
ADDMSG(&f->msgs, msg_message("detectforbidden", "unit region", u, sh->region));
|
||||
}
|
||||
else if (check_leuchtturm(current_point, NULL)) {
|
||||
else if (lighthouse_guarded(current_point)) {
|
||||
ADDMSG(&f->msgs, msg_message("sailnolandingstorm", "ship region", sh, next_point));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -1353,6 +1353,13 @@ static void add_seen_nb(faction *f, region *r, seen_mode mode) {
|
|||
update_interval(f, last);
|
||||
}
|
||||
|
||||
static void add_seen_lighthouse(region *r, faction *f)
|
||||
{
|
||||
if (r->terrain->flags & SEA_REGION) {
|
||||
add_seen_nb(f, r, seen_lighthouse);
|
||||
}
|
||||
}
|
||||
|
||||
/** mark all regions seen by the lighthouse.
|
||||
*/
|
||||
static void prepare_lighthouse_ql(faction *f, selist *rlist) {
|
||||
|
@ -1361,9 +1368,7 @@ static void prepare_lighthouse_ql(faction *f, selist *rlist) {
|
|||
|
||||
for (ql = rlist, qi = 0; ql; selist_advance(&ql, &qi, 1)) {
|
||||
region *rl = (region *)selist_get(ql, qi);
|
||||
if (!fval(rl->terrain, FORBIDDEN_REGION)) {
|
||||
add_seen_nb(f, rl, seen_lighthouse);
|
||||
}
|
||||
add_seen_lighthouse(rl, f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1382,9 +1387,7 @@ static void prepare_lighthouse(faction *f, region *r, int range)
|
|||
assert(n > 0 && n <= 64);
|
||||
for (i = 0; i != n; ++i) {
|
||||
region *rl = result[i];
|
||||
if (!fval(rl->terrain, FORBIDDEN_REGION)) {
|
||||
add_seen_nb(f, rl, seen_lighthouse);
|
||||
}
|
||||
add_seen_lighthouse(rl, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1592,7 +1595,7 @@ void prepare_report(report_context *ctx, faction *f)
|
|||
if (rule_region_owners && f == region_get_owner(r)) {
|
||||
for (b = rbuildings(r); b; b = b->next) {
|
||||
if (b && b->type == bt_lighthouse) {
|
||||
/* region owners get maximm range */
|
||||
/* region owners get maximum range */
|
||||
int lhr = lighthouse_range(b, NULL, NULL);
|
||||
if (lhr > range) range = lhr;
|
||||
}
|
||||
|
@ -1630,7 +1633,7 @@ void prepare_report(report_context *ctx, faction *f)
|
|||
/* unit is one of ours, and inside the current lighthouse */
|
||||
if (br == 0) {
|
||||
/* lazy-calculate the range */
|
||||
br = lighthouse_range(u->building, f, u);
|
||||
br = lighthouse_range(b, f, u);
|
||||
}
|
||||
if (br > range) {
|
||||
range = br;
|
||||
|
|
|
@ -530,7 +530,7 @@ void test_prepare_lighthouse_capacity(CuTest *tc) {
|
|||
static void test_prepare_lighthouse(CuTest *tc) {
|
||||
report_context ctx;
|
||||
faction *f;
|
||||
region *r1, *r2, *r3;
|
||||
region *r1, *r2, *r3, *r4;
|
||||
unit *u;
|
||||
building *b;
|
||||
building_type *btype;
|
||||
|
@ -543,6 +543,7 @@ static void test_prepare_lighthouse(CuTest *tc) {
|
|||
r1 = test_create_region(0, 0, t_plain);
|
||||
r2 = test_create_region(1, 0, t_ocean);
|
||||
r3 = test_create_region(2, 0, t_ocean);
|
||||
r4 = test_create_region(0, 1, t_plain);
|
||||
btype = test_create_buildingtype("lighthouse");
|
||||
b = test_create_building(r1, btype);
|
||||
b->flags |= BLD_MAINTAINED;
|
||||
|
@ -557,6 +558,7 @@ static void test_prepare_lighthouse(CuTest *tc) {
|
|||
CuAssertIntEquals(tc, seen_unit, r1->seen.mode);
|
||||
CuAssertIntEquals(tc, seen_lighthouse, r2->seen.mode);
|
||||
CuAssertIntEquals(tc, seen_neighbour, r3->seen.mode);
|
||||
CuAssertIntEquals(tc, seen_neighbour, r4->seen.mode);
|
||||
finish_reports(&ctx);
|
||||
test_teardown();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue