diff --git a/src/kernel/pathfinder.c b/src/kernel/pathfinder.c index f2103f63f..15ac0e966 100644 --- a/src/kernel/pathfinder.c +++ b/src/kernel/pathfinder.c @@ -79,7 +79,7 @@ static void free_nodes(node * root) } } -struct selist *regions_in_range(struct region *handle_start, int maxdist, +struct selist *path_regions_in_range(struct region *handle_start, int maxdist, bool(*allowed) (const struct region *, const struct region *)) { selist * rlist = NULL; diff --git a/src/kernel/pathfinder.h b/src/kernel/pathfinder.h index 9557fe735..df4bfbe80 100644 --- a/src/kernel/pathfinder.h +++ b/src/kernel/pathfinder.h @@ -8,15 +8,10 @@ extern "C" { const struct region *target, int maxlen, bool(*allowed) (const struct region *, const struct region *)); extern bool path_exists(struct region *handle_start, const struct region *target, - int maxlen, bool(*allowed) (const struct region *, - const struct region *)); - extern bool allowed_swim(const struct region *src, - const struct region *target); - extern bool allowed_fly(const struct region *src, - const struct region *target); - extern bool allowed_walk(const struct region *src, - const struct region *target); - extern struct selist *regions_in_range(struct region *src, int maxdist, + int maxlen, bool(*allowed) (const struct region *, const struct region *)); + extern bool allowed_fly(const struct region *src, const struct region *target); + extern bool allowed_walk(const struct region *src, const struct region *target); + extern struct selist *path_regions_in_range(struct region *src, int maxdist, bool(*allowed) (const struct region *, const struct region *)); extern void pathfinder_cleanup(void); diff --git a/src/monsters.c b/src/monsters.c index 34214a342..129c8f76c 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -497,7 +497,7 @@ static attrib *set_new_dragon_target(unit * u, region * r, int range) { int max_affinity = 0; region *max_region = NULL; - selist *ql, *rlist = regions_in_range(r, range, allowed_dragon); + selist *ql, *rlist = path_regions_in_range(r, range, allowed_dragon); int qi; for (qi = 0, ql = rlist; ql; selist_advance(&ql, &qi, 1)) { diff --git a/src/spells.c b/src/spells.c index fbd4d71d5..0b17578fe 100644 --- a/src/spells.c +++ b/src/spells.c @@ -5423,19 +5423,22 @@ int sp_fetchastral(castorder * co) return cast_level; } -#define SHOWASTRAL_IS_BORKED +static bool cb_not_astral_blocked(const struct region *rt) { + return !is_cursed(rt->attribs, &ct_astralblock); +} + +#undef SHOWASTRAL_IS_BORKED #ifndef SHOWASTRAL_IS_BORKED +#define SHOWASTRAL_MAX_RADIUS 5 int sp_showastral(castorder * co) { - unit *u; region *rt; int n = 0; - int c = 0; - region_list *rl, *rl2; region *r = co_get_region(co); unit *mage = co_get_caster(co); - int cast_level = co->level; - double power = co->force; + int force = (int) co->force; + int radius = (force < SHOWASTRAL_MAX_RADIUS) ? force : SHOWASTRAL_MAX_RADIUS; + region *targets[4 * SHOWASTRAL_MAX_RADIUS * SHOWASTRAL_MAX_RADIUS]; switch (getplaneid(r)) { case 0: @@ -5455,62 +5458,21 @@ int sp_showastral(castorder * co) return 0; } - rl = all_in_range(rt, power / 5); - - /* Erst Einheiten zaehlen, fuer die Grammatik. */ - - for (rl2 = rl; rl2; rl2 = rl2->next) { - region *r2 = rl2->data; - if (!is_cursed(r2->attribs, &ct_astralblock)) { - for (u = r2->units; u; u = u->next) { - n++; - } - } - } - + n = regions_in_range(rt, radius, cb_not_astral_blocked, targets); if (n == 0) { /* sprintf(buf, "%s kann niemanden im astralen Nebel entdecken.", unitname(mage)); */ cmistake(mage, co->order, 220, MSG_MAGIC); } else { - - /* Ausgeben */ - - sprintf(buf, "%s hat eine Vision der astralen Ebene. Im astralen " - "Nebel zu erkennen sind ", unitname(mage)); - - for (rl2 = rl; rl2; rl2 = rl2->next) { - if (!is_cursed(rl2->data->attribs, &ct_astralblock)) { - for (u = rl2->data->units; u; u = u->next) { - c++; - scat(unitname(u)); - scat(" ("); - if (!fval(u, UFL_ANON_FACTION)) { - scat(factionname(u->faction)); - scat(", "); - } - icat(u->number); - scat(" "); - scat(LOC(mage->faction->locale, rc_name_s(u_race(u), (u->number == 1) ? NAME_SINGULAR : NAME_PLURAL))); - scat(", Entfernung "); - icat(distance(rl2->data, rt)); - scat(")"); - if (c == n - 1) { - scat(" und "); - } - else if (c < n - 1) { - scat(", "); - } - } - } + int i; + for (i = 0; i != n; ++i) { + region *rt = targets[i]; + set_observer(rt, mage->faction, (int)(co->force / 2), 2); } - scat("."); - addmessage(r, mage->faction, buf, MSG_MAGIC, ML_INFO); } - free_regionlist(rl); - return cast_level; + return co->level; } #endif @@ -5519,7 +5481,7 @@ int sp_viewreality(castorder * co) { region *r = co_get_region(co); unit *mage = co_get_caster(co); - int cast_level = co->level; + int force = (int)co->force; message *m; region *rl[MAX_SCHEMES]; int num; @@ -5537,7 +5499,7 @@ int sp_viewreality(castorder * co) for (i = 0; i != num; ++i) { region *rt = rl[i]; if (!is_cursed(rt->attribs, &ct_astralblock)) { - set_observer(rt, mage->faction, co->level / 2, 2); + set_observer(rt, mage->faction, force / 2, 2); } } } @@ -5546,7 +5508,7 @@ int sp_viewreality(castorder * co) r_addmessage(r, mage->faction, m); msg_release(m); - return cast_level; + return co->level; } static void cb_disrupt_astral(region *r2, void *cbdata) { diff --git a/src/spells.test.c b/src/spells.test.c index 6ee4a305c..6261bcacd 100644 --- a/src/spells.test.c +++ b/src/spells.test.c @@ -116,7 +116,7 @@ static void test_bad_dreams(CuTest *tc) { } static void test_view_reality(CuTest *tc) { - region *r, *ra; + region *r, *ra, *rx; faction *f; unit *u; castorder co; @@ -127,12 +127,13 @@ static void test_view_reality(CuTest *tc) { mt_create_va(mt_new("viewreality_effect", NULL), "unit:unit", MT_NEW_END); r = test_create_region(0, 0, NULL); + rx = test_create_region(0, TP_RADIUS+1, NULL); ra = test_create_region(real2tp(r->x), real2tp(r->y), NULL); ra->_plane = get_astralplane(); f = test_create_faction(NULL); u = test_create_unit(f, r); - test_create_castorder(&co, u, 10, 10., 0, NULL); + test_create_castorder(&co, u, 10, 10.0, 0, NULL); CuAssertIntEquals(tc, -1, get_observer(r, f)); CuAssertIntEquals(tc, 0, sp_viewreality(&co)); CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "spell_astral_only")); @@ -141,11 +142,12 @@ static void test_view_reality(CuTest *tc) { test_clear_messagelist(&f->msgs); move_unit(u, ra, NULL); - test_create_castorder(&co, u, 9, 10., 0, NULL); + test_create_castorder(&co, u, 9, 10.0, 0, NULL); CuAssertIntEquals(tc, -1, get_observer(r, f)); CuAssertIntEquals(tc, 9, sp_viewreality(&co)); CuAssertPtrEquals(tc, NULL, test_find_messagetype(f->msgs, "spell_astral_only")); - CuAssertIntEquals(tc, 4, get_observer(r, f)); + CuAssertIntEquals(tc, 5, get_observer(r, f)); + CuAssertIntEquals(tc, -1, get_observer(rx, f)); CuAssertPtrEquals(tc, f, (void *)ra->individual_messages->viewer); CuAssertPtrNotNull(tc, test_find_messagetype(ra->individual_messages->msgs, "viewreality_effect")); free_castorder(&co); diff --git a/src/teleport.c b/src/teleport.c index ecd3834bf..faa2f7103 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -43,32 +43,37 @@ static region *tpregion(const region * r) return rt; } +int regions_in_range(const region * r, int radius, bool(*valid) (const region *), region *result[]) +{ + int x, y, num = 0; + const struct plane *pl = rplane(r); + for (x = -radius; x <= +radius; ++x) { + for (y = -radius; y <= radius; ++y) { + int dist = koor_distance(0, 0, x, y); + + if (dist <= radius) { + region *rn; + int nx = r->x + x, ny = r->y + y; + pnormalize(&nx, &ny, pl); + rn = findregion(nx, ny); + if (rn != NULL && (valid == NULL || valid(rn))) { + if (result) { + result[num] = rn; + } + ++num; + } + } + } + } + return num; +} int get_astralregions(const region * r, bool(*valid) (const region *), region *result[]) { assert(is_astral(r)); r = r_astral_to_standard(r); if (r) { - int x, y, num = 0; - for (x = -TP_RADIUS; x <= +TP_RADIUS; ++x) { - for (y = -TP_RADIUS; y <= +TP_RADIUS; ++y) { - region *rn; - int dist = koor_distance(0, 0, x, y); - - if (dist <= TP_RADIUS) { - int nx = r->x + x, ny = r->y + y; - pnormalize(&nx, &ny, rplane(r)); - rn = findregion(nx, ny); - if (rn != NULL && (valid == NULL || valid(rn))) { - if (result) { - result[num] = rn; - } - ++num; - } - } - } - } - return num; + return regions_in_range(r, TP_RADIUS, valid, result); } return 0; } diff --git a/src/teleport.h b/src/teleport.h index d91bed3df..340e38667 100644 --- a/src/teleport.h +++ b/src/teleport.h @@ -20,6 +20,7 @@ extern "C" { bool is_astral(const struct region *r); struct plane *get_astralplane(void); int get_astralregions(const struct region * r, bool(*valid) (const struct region *), struct region *result[]); + int regions_in_range(const struct region * r, int radius, bool(*valid) (const struct region *), struct region *result[]); void create_teleport_plane(void); void spawn_braineaters(float chance);